fimc-is-regs.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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_intsr0_intsd0(struct fimc_is *is)
  32. {
  33. unsigned int timeout = 2000;
  34. u32 cfg, status;
  35. cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
  36. status = INTSR0_GET_INTSD(0, cfg);
  37. while (status) {
  38. cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
  39. status = INTSR0_GET_INTSD(0, cfg);
  40. if (timeout == 0) {
  41. dev_warn(&is->pdev->dev, "%s timeout\n",
  42. __func__);
  43. return -ETIME;
  44. }
  45. timeout--;
  46. udelay(1);
  47. }
  48. return 0;
  49. }
  50. int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is)
  51. {
  52. unsigned int timeout = 2000;
  53. u32 cfg, status;
  54. cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
  55. status = INTMSR0_GET_INTMSD(0, cfg);
  56. while (status) {
  57. cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
  58. status = INTMSR0_GET_INTMSD(0, cfg);
  59. if (timeout == 0) {
  60. dev_warn(&is->pdev->dev, "%s timeout\n",
  61. __func__);
  62. return -ETIME;
  63. }
  64. timeout--;
  65. udelay(1);
  66. }
  67. return 0;
  68. }
  69. int fimc_is_hw_set_param(struct fimc_is *is)
  70. {
  71. struct chain_config *config = &is->config[is->config_index];
  72. unsigned int param_count = __get_pending_param_count(is);
  73. fimc_is_hw_wait_intmsr0_intmsd0(is);
  74. mcuctl_write(HIC_SET_PARAMETER, is, MCUCTL_REG_ISSR(0));
  75. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  76. mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2));
  77. mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3));
  78. mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4));
  79. mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5));
  80. fimc_is_hw_set_intgr0_gd0(is);
  81. return 0;
  82. }
  83. static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is)
  84. {
  85. fimc_is_hw_wait_intmsr0_intmsd0(is);
  86. mcuctl_write(HIC_SET_TUNE, is, MCUCTL_REG_ISSR(0));
  87. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  88. mcuctl_write(is->h2i_cmd.entry_id, is, MCUCTL_REG_ISSR(2));
  89. fimc_is_hw_set_intgr0_gd0(is);
  90. return 0;
  91. }
  92. #define FIMC_IS_MAX_PARAMS 4
  93. int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args)
  94. {
  95. int i;
  96. if (num_args > FIMC_IS_MAX_PARAMS)
  97. return -EINVAL;
  98. is->i2h_cmd.num_args = num_args;
  99. for (i = 0; i < FIMC_IS_MAX_PARAMS; i++) {
  100. if (i < num_args)
  101. is->i2h_cmd.args[i] = mcuctl_read(is,
  102. MCUCTL_REG_ISSR(12 + i));
  103. else
  104. is->i2h_cmd.args[i] = 0;
  105. }
  106. return 0;
  107. }
  108. void fimc_is_hw_set_sensor_num(struct fimc_is *is)
  109. {
  110. pr_debug("setting sensor index to: %d\n", is->sensor_index);
  111. mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
  112. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  113. mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
  114. mcuctl_write(FIMC_IS_SENSOR_NUM, is, MCUCTL_REG_ISSR(3));
  115. }
  116. void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
  117. {
  118. if (is->sensor_index != index)
  119. return;
  120. fimc_is_hw_wait_intmsr0_intmsd0(is);
  121. mcuctl_write(HIC_CLOSE_SENSOR, is, MCUCTL_REG_ISSR(0));
  122. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  123. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(2));
  124. fimc_is_hw_set_intgr0_gd0(is);
  125. }
  126. void fimc_is_hw_get_setfile_addr(struct fimc_is *is)
  127. {
  128. fimc_is_hw_wait_intmsr0_intmsd0(is);
  129. mcuctl_write(HIC_GET_SET_FILE_ADDR, is, MCUCTL_REG_ISSR(0));
  130. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  131. fimc_is_hw_set_intgr0_gd0(is);
  132. }
  133. void fimc_is_hw_load_setfile(struct fimc_is *is)
  134. {
  135. fimc_is_hw_wait_intmsr0_intmsd0(is);
  136. mcuctl_write(HIC_LOAD_SET_FILE, is, MCUCTL_REG_ISSR(0));
  137. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  138. fimc_is_hw_set_intgr0_gd0(is);
  139. }
  140. int fimc_is_hw_change_mode(struct fimc_is *is)
  141. {
  142. const u8 cmd[] = {
  143. HIC_PREVIEW_STILL, HIC_PREVIEW_VIDEO,
  144. HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO,
  145. };
  146. if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd)))
  147. return -EINVAL;
  148. mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0));
  149. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  150. mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2));
  151. fimc_is_hw_set_intgr0_gd0(is);
  152. return 0;
  153. }
  154. void fimc_is_hw_stream_on(struct fimc_is *is)
  155. {
  156. fimc_is_hw_wait_intmsr0_intmsd0(is);
  157. mcuctl_write(HIC_STREAM_ON, is, MCUCTL_REG_ISSR(0));
  158. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  159. mcuctl_write(0, is, MCUCTL_REG_ISSR(2));
  160. fimc_is_hw_set_intgr0_gd0(is);
  161. }
  162. void fimc_is_hw_stream_off(struct fimc_is *is)
  163. {
  164. fimc_is_hw_wait_intmsr0_intmsd0(is);
  165. mcuctl_write(HIC_STREAM_OFF, is, MCUCTL_REG_ISSR(0));
  166. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  167. fimc_is_hw_set_intgr0_gd0(is);
  168. }
  169. void fimc_is_hw_subip_power_off(struct fimc_is *is)
  170. {
  171. fimc_is_hw_wait_intmsr0_intmsd0(is);
  172. mcuctl_write(HIC_POWER_DOWN, is, MCUCTL_REG_ISSR(0));
  173. mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
  174. fimc_is_hw_set_intgr0_gd0(is);
  175. }
  176. int fimc_is_itf_s_param(struct fimc_is *is, bool update)
  177. {
  178. int ret;
  179. if (update)
  180. __is_hw_update_params(is);
  181. fimc_is_mem_barrier();
  182. clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
  183. fimc_is_hw_set_param(is);
  184. ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1,
  185. FIMC_IS_CONFIG_TIMEOUT);
  186. if (ret < 0)
  187. dev_err(&is->pdev->dev, "%s() timeout\n", __func__);
  188. return ret;
  189. }
  190. int fimc_is_itf_mode_change(struct fimc_is *is)
  191. {
  192. int ret;
  193. clear_bit(IS_ST_CHANGE_MODE, &is->state);
  194. fimc_is_hw_change_mode(is);
  195. ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1,
  196. FIMC_IS_CONFIG_TIMEOUT);
  197. if (ret < 0)
  198. dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n",
  199. __func__, is->config_index);
  200. return ret;
  201. }