fimc-is-regs.c 5.8 KB

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