fimc-is-regs.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
  3. *
  4. * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
  5. *
  6. * Authors: Younghwan Joo <yhwan.joo@samsung.com>
  7. * Sylwester Nawrocki <s.nawrocki@samsung.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/delay.h>
  14. #include "fimc-is.h"
  15. #include "fimc-is-command.h"
  16. #include "fimc-is-regs.h"
  17. #include "fimc-is-sensor.h"
  18. void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int nr)
  19. {
  20. mcuctl_write(1UL << nr, is, MCUCTL_REG_INTCR1);
  21. }
  22. void fimc_is_fw_clear_irq2(struct fimc_is *is)
  23. {
  24. u32 cfg = mcuctl_read(is, MCUCTL_REG_INTSR2);
  25. mcuctl_write(cfg, is, MCUCTL_REG_INTCR2);
  26. }
  27. void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is)
  28. {
  29. mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0);
  30. }
  31. int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is)
  32. {
  33. unsigned int timeout = 2000;
  34. u32 cfg, status;
  35. do {
  36. cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
  37. status = INTMSR0_GET_INTMSD(0, cfg);
  38. if (--timeout == 0) {
  39. dev_warn(&is->pdev->dev, "%s timeout\n",
  40. __func__);
  41. return -ETIMEDOUT;
  42. }
  43. udelay(1);
  44. } while (status != 0);
  45. return 0;
  46. }
  47. int fimc_is_hw_set_param(struct fimc_is *is)
  48. {
  49. struct chain_config *config = &is->config[is->config_index];
  50. unsigned int param_count = __get_pending_param_count(is);
  51. fimc_is_hw_wait_intmsr0_intmsd0(is);
  52. mcuctl_write(HIC_SET_PARAMETER, is, MCUCTL_REG_ISSR(0));
  53. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  54. mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2));
  55. mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3));
  56. mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4));
  57. mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5));
  58. fimc_is_hw_set_intgr0_gd0(is);
  59. return 0;
  60. }
  61. static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is)
  62. {
  63. fimc_is_hw_wait_intmsr0_intmsd0(is);
  64. mcuctl_write(HIC_SET_TUNE, is, MCUCTL_REG_ISSR(0));
  65. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  66. mcuctl_write(is->h2i_cmd.entry_id, is, MCUCTL_REG_ISSR(2));
  67. fimc_is_hw_set_intgr0_gd0(is);
  68. return 0;
  69. }
  70. #define FIMC_IS_MAX_PARAMS 4
  71. int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args)
  72. {
  73. int i;
  74. if (num_args > FIMC_IS_MAX_PARAMS)
  75. return -EINVAL;
  76. is->i2h_cmd.num_args = num_args;
  77. for (i = 0; i < FIMC_IS_MAX_PARAMS; i++) {
  78. if (i < num_args)
  79. is->i2h_cmd.args[i] = mcuctl_read(is,
  80. MCUCTL_REG_ISSR(12 + i));
  81. else
  82. is->i2h_cmd.args[i] = 0;
  83. }
  84. return 0;
  85. }
  86. void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask)
  87. {
  88. if (hweight32(mask) == 1) {
  89. dev_err(&is->pdev->dev, "%s(): not enough buffers (mask %#x)\n",
  90. __func__, mask);
  91. return;
  92. }
  93. if (mcuctl_read(is, MCUCTL_REG_ISSR(23)) != 0)
  94. dev_dbg(&is->pdev->dev, "non-zero DMA buffer mask\n");
  95. mcuctl_write(mask, is, MCUCTL_REG_ISSR(23));
  96. }
  97. void fimc_is_hw_set_sensor_num(struct fimc_is *is)
  98. {
  99. pr_debug("setting sensor index to: %d\n", is->sensor_index);
  100. mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
  101. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  102. mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
  103. mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3));
  104. }
  105. void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
  106. {
  107. if (is->sensor_index != index)
  108. return;
  109. fimc_is_hw_wait_intmsr0_intmsd0(is);
  110. mcuctl_write(HIC_CLOSE_SENSOR, is, MCUCTL_REG_ISSR(0));
  111. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  112. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(2));
  113. fimc_is_hw_set_intgr0_gd0(is);
  114. }
  115. void fimc_is_hw_get_setfile_addr(struct fimc_is *is)
  116. {
  117. fimc_is_hw_wait_intmsr0_intmsd0(is);
  118. mcuctl_write(HIC_GET_SET_FILE_ADDR, is, MCUCTL_REG_ISSR(0));
  119. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  120. fimc_is_hw_set_intgr0_gd0(is);
  121. }
  122. void fimc_is_hw_load_setfile(struct fimc_is *is)
  123. {
  124. fimc_is_hw_wait_intmsr0_intmsd0(is);
  125. mcuctl_write(HIC_LOAD_SET_FILE, is, MCUCTL_REG_ISSR(0));
  126. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  127. fimc_is_hw_set_intgr0_gd0(is);
  128. }
  129. int fimc_is_hw_change_mode(struct fimc_is *is)
  130. {
  131. const u8 cmd[] = {
  132. HIC_PREVIEW_STILL, HIC_PREVIEW_VIDEO,
  133. HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO,
  134. };
  135. if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd)))
  136. return -EINVAL;
  137. mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0));
  138. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  139. mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2));
  140. fimc_is_hw_set_intgr0_gd0(is);
  141. return 0;
  142. }
  143. void fimc_is_hw_stream_on(struct fimc_is *is)
  144. {
  145. fimc_is_hw_wait_intmsr0_intmsd0(is);
  146. mcuctl_write(HIC_STREAM_ON, is, MCUCTL_REG_ISSR(0));
  147. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  148. mcuctl_write(0, is, MCUCTL_REG_ISSR(2));
  149. fimc_is_hw_set_intgr0_gd0(is);
  150. }
  151. void fimc_is_hw_stream_off(struct fimc_is *is)
  152. {
  153. fimc_is_hw_wait_intmsr0_intmsd0(is);
  154. mcuctl_write(HIC_STREAM_OFF, is, MCUCTL_REG_ISSR(0));
  155. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  156. fimc_is_hw_set_intgr0_gd0(is);
  157. }
  158. void fimc_is_hw_subip_power_off(struct fimc_is *is)
  159. {
  160. fimc_is_hw_wait_intmsr0_intmsd0(is);
  161. mcuctl_write(HIC_POWER_DOWN, is, MCUCTL_REG_ISSR(0));
  162. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  163. fimc_is_hw_set_intgr0_gd0(is);
  164. }
  165. int fimc_is_itf_s_param(struct fimc_is *is, bool update)
  166. {
  167. int ret;
  168. if (update)
  169. __is_hw_update_params(is);
  170. fimc_is_mem_barrier();
  171. clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
  172. fimc_is_hw_set_param(is);
  173. ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1,
  174. FIMC_IS_CONFIG_TIMEOUT);
  175. if (ret < 0)
  176. dev_err(&is->pdev->dev, "%s() timeout\n", __func__);
  177. return ret;
  178. }
  179. int fimc_is_itf_mode_change(struct fimc_is *is)
  180. {
  181. int ret;
  182. clear_bit(IS_ST_CHANGE_MODE, &is->state);
  183. fimc_is_hw_change_mode(is);
  184. ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1,
  185. FIMC_IS_CONFIG_TIMEOUT);
  186. if (ret < 0)
  187. dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n",
  188. __func__, is->config_index);
  189. return ret;
  190. }