solo6x10-enc.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
  4. *
  5. * Original author:
  6. * Ben Collins <[email protected]>
  7. *
  8. * Additional work by:
  9. * John Brooks <[email protected]>
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/font.h>
  13. #include <linux/bitrev.h>
  14. #include <linux/slab.h>
  15. #include "solo6x10.h"
  16. #define VI_PROG_HSIZE (1280 - 16)
  17. #define VI_PROG_VSIZE (1024 - 16)
  18. #define IRQ_LEVEL 2
  19. static void solo_capture_config(struct solo_dev *solo_dev)
  20. {
  21. unsigned long height;
  22. unsigned long width;
  23. void *buf;
  24. int i;
  25. solo_reg_write(solo_dev, SOLO_CAP_BASE,
  26. SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
  27. - SOLO_CAP_PAGE_SIZE) >> 16)
  28. | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
  29. /* XXX: Undocumented bits at b17 and b24 */
  30. if (solo_dev->type == SOLO_DEV_6110) {
  31. /* NOTE: Ref driver has (62 << 24) here as well, but it causes
  32. * wacked out frame timing on 4-port 6110. */
  33. solo_reg_write(solo_dev, SOLO_CAP_BTW,
  34. (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
  35. SOLO_CAP_MAX_BANDWIDTH(36));
  36. } else {
  37. solo_reg_write(solo_dev, SOLO_CAP_BTW,
  38. (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
  39. SOLO_CAP_MAX_BANDWIDTH(32));
  40. }
  41. /* Set scale 1, 9 dimension */
  42. width = solo_dev->video_hsize;
  43. height = solo_dev->video_vsize;
  44. solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
  45. SOLO_DIM_H_MB_NUM(width / 16) |
  46. SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
  47. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  48. /* Set scale 2, 10 dimension */
  49. width = solo_dev->video_hsize / 2;
  50. height = solo_dev->video_vsize;
  51. solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
  52. SOLO_DIM_H_MB_NUM(width / 16) |
  53. SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
  54. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  55. /* Set scale 3, 11 dimension */
  56. width = solo_dev->video_hsize / 2;
  57. height = solo_dev->video_vsize / 2;
  58. solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
  59. SOLO_DIM_H_MB_NUM(width / 16) |
  60. SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
  61. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  62. /* Set scale 4, 12 dimension */
  63. width = solo_dev->video_hsize / 3;
  64. height = solo_dev->video_vsize / 3;
  65. solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
  66. SOLO_DIM_H_MB_NUM(width / 16) |
  67. SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
  68. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  69. /* Set scale 5, 13 dimension */
  70. width = solo_dev->video_hsize / 4;
  71. height = solo_dev->video_vsize / 2;
  72. solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
  73. SOLO_DIM_H_MB_NUM(width / 16) |
  74. SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
  75. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  76. /* Progressive */
  77. width = VI_PROG_HSIZE;
  78. height = VI_PROG_VSIZE;
  79. solo_reg_write(solo_dev, SOLO_DIM_PROG,
  80. SOLO_DIM_H_MB_NUM(width / 16) |
  81. SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
  82. SOLO_DIM_V_MB_NUM_FIELD(height / 16));
  83. /* Clear OSD */
  84. solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
  85. solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
  86. solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
  87. 0xF0 << 16 | 0x80 << 8 | 0x80);
  88. if (solo_dev->type == SOLO_DEV_6010)
  89. solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
  90. SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
  91. else
  92. solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
  93. | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
  94. /* Clear OSG buffer */
  95. buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
  96. if (!buf)
  97. return;
  98. for (i = 0; i < solo_dev->nr_chans; i++) {
  99. solo_p2m_dma(solo_dev, 1, buf,
  100. SOLO_EOSD_EXT_ADDR +
  101. (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
  102. SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
  103. }
  104. kfree(buf);
  105. }
  106. #define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
  107. /* Should be called with enable_lock held */
  108. int solo_osd_print(struct solo_enc_dev *solo_enc)
  109. {
  110. struct solo_dev *solo_dev = solo_enc->solo_dev;
  111. u8 *str = solo_enc->osd_text;
  112. u8 *buf = solo_enc->osd_buf;
  113. u32 reg;
  114. const struct font_desc *vga = find_font("VGA8x16");
  115. const u8 *vga_data;
  116. int i, j;
  117. if (WARN_ON_ONCE(!vga))
  118. return -ENODEV;
  119. reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
  120. if (!*str) {
  121. /* Disable OSD on this channel */
  122. reg &= ~(1 << solo_enc->ch);
  123. goto out;
  124. }
  125. memset(buf, 0, SOLO_OSD_WRITE_SIZE);
  126. vga_data = (const u8 *)vga->data;
  127. for (i = 0; *str; i++, str++) {
  128. for (j = 0; j < 16; j++) {
  129. buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
  130. bitrev8(vga_data[(*str << 4) | j]);
  131. }
  132. }
  133. solo_p2m_dma(solo_dev, 1, buf,
  134. SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
  135. SOLO_OSD_WRITE_SIZE, 0, 0);
  136. /* Enable OSD on this channel */
  137. reg |= (1 << solo_enc->ch);
  138. out:
  139. solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
  140. return 0;
  141. }
  142. /*
  143. * Set channel Quality Profile (0-3).
  144. */
  145. void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
  146. unsigned int qp)
  147. {
  148. unsigned long flags;
  149. unsigned int idx, reg;
  150. if ((ch > 31) || (qp > 3))
  151. return;
  152. if (solo_dev->type == SOLO_DEV_6010)
  153. return;
  154. if (ch < 16) {
  155. idx = 0;
  156. reg = SOLO_VE_JPEG_QP_CH_L;
  157. } else {
  158. ch -= 16;
  159. idx = 1;
  160. reg = SOLO_VE_JPEG_QP_CH_H;
  161. }
  162. ch *= 2;
  163. spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
  164. solo_dev->jpeg_qp[idx] &= ~(3 << ch);
  165. solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
  166. solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
  167. spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
  168. }
  169. int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
  170. {
  171. int idx;
  172. if (solo_dev->type == SOLO_DEV_6010)
  173. return 2;
  174. if (WARN_ON_ONCE(ch > 31))
  175. return 2;
  176. if (ch < 16) {
  177. idx = 0;
  178. } else {
  179. ch -= 16;
  180. idx = 1;
  181. }
  182. ch *= 2;
  183. return (solo_dev->jpeg_qp[idx] >> ch) & 3;
  184. }
  185. #define SOLO_QP_INIT 0xaaaaaaaa
  186. static void solo_jpeg_config(struct solo_dev *solo_dev)
  187. {
  188. if (solo_dev->type == SOLO_DEV_6010) {
  189. solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
  190. (2 << 24) | (2 << 16) | (2 << 8) | 2);
  191. } else {
  192. solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
  193. (4 << 24) | (3 << 16) | (2 << 8) | 1);
  194. }
  195. spin_lock_init(&solo_dev->jpeg_qp_lock);
  196. /* Initialize Quality Profile for all channels */
  197. solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
  198. solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
  199. solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
  200. solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
  201. (SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
  202. ((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
  203. solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
  204. if (solo_dev->type == SOLO_DEV_6110) {
  205. solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
  206. (0 << 16) | (30 << 8) | 60);
  207. }
  208. }
  209. static void solo_mp4e_config(struct solo_dev *solo_dev)
  210. {
  211. int i;
  212. u32 cfg;
  213. solo_reg_write(solo_dev, SOLO_VE_CFG0,
  214. SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
  215. SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
  216. SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
  217. cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
  218. | SOLO_VE_MOTION_MODE(0);
  219. if (solo_dev->type != SOLO_DEV_6010) {
  220. cfg |= SOLO_VE_MPEG_SIZE_H(
  221. (SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
  222. cfg |= SOLO_VE_JPEG_SIZE_H(
  223. (SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
  224. }
  225. solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
  226. solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
  227. solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
  228. solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
  229. if (solo_dev->type == SOLO_DEV_6110)
  230. solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
  231. solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
  232. solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
  233. solo_reg_write(solo_dev, SOLO_VE_ATTR,
  234. SOLO_VE_LITTLE_ENDIAN |
  235. SOLO_COMP_ATTR_FCODE(1) |
  236. SOLO_COMP_TIME_INC(0) |
  237. SOLO_COMP_TIME_WIDTH(15) |
  238. SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
  239. for (i = 0; i < solo_dev->nr_chans; i++) {
  240. solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
  241. (SOLO_EREF_EXT_ADDR(solo_dev) +
  242. (i * SOLO_EREF_EXT_SIZE)) >> 16);
  243. solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
  244. (SOLO_EREF_EXT_ADDR(solo_dev) +
  245. ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
  246. }
  247. if (solo_dev->type == SOLO_DEV_6110) {
  248. solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
  249. } else {
  250. for (i = 0; i < solo_dev->nr_chans; i++)
  251. solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
  252. }
  253. }
  254. int solo_enc_init(struct solo_dev *solo_dev)
  255. {
  256. int i;
  257. solo_capture_config(solo_dev);
  258. solo_mp4e_config(solo_dev);
  259. solo_jpeg_config(solo_dev);
  260. for (i = 0; i < solo_dev->nr_chans; i++) {
  261. solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
  262. solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
  263. }
  264. return 0;
  265. }
  266. void solo_enc_exit(struct solo_dev *solo_dev)
  267. {
  268. int i;
  269. for (i = 0; i < solo_dev->nr_chans; i++) {
  270. solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
  271. solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
  272. }
  273. }