sti_vid.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) STMicroelectronics SA 2014
  4. * Author: Fabien Dessenne <[email protected]> for STMicroelectronics.
  5. */
  6. #include <linux/seq_file.h>
  7. #include <drm/drm_debugfs.h>
  8. #include <drm/drm_file.h>
  9. #include <drm/drm_print.h>
  10. #include "sti_plane.h"
  11. #include "sti_vid.h"
  12. #include "sti_vtg.h"
  13. /* Registers */
  14. #define VID_CTL 0x00
  15. #define VID_ALP 0x04
  16. #define VID_CLF 0x08
  17. #define VID_VPO 0x0C
  18. #define VID_VPS 0x10
  19. #define VID_KEY1 0x28
  20. #define VID_KEY2 0x2C
  21. #define VID_MPR0 0x30
  22. #define VID_MPR1 0x34
  23. #define VID_MPR2 0x38
  24. #define VID_MPR3 0x3C
  25. #define VID_MST 0x68
  26. #define VID_BC 0x70
  27. #define VID_TINT 0x74
  28. #define VID_CSAT 0x78
  29. /* Registers values */
  30. #define VID_CTL_IGNORE (BIT(31) | BIT(30))
  31. #define VID_CTL_PSI_ENABLE (BIT(2) | BIT(1) | BIT(0))
  32. #define VID_ALP_OPAQUE 0x00000080
  33. #define VID_BC_DFLT 0x00008000
  34. #define VID_TINT_DFLT 0x00000000
  35. #define VID_CSAT_DFLT 0x00000080
  36. /* YCbCr to RGB BT709:
  37. * R = Y+1.5391Cr
  38. * G = Y-0.4590Cr-0.1826Cb
  39. * B = Y+1.8125Cb */
  40. #define VID_MPR0_BT709 0x0A800000
  41. #define VID_MPR1_BT709 0x0AC50000
  42. #define VID_MPR2_BT709 0x07150545
  43. #define VID_MPR3_BT709 0x00000AE8
  44. /* YCbCr to RGB BT709:
  45. * R = Y+1.3711Cr
  46. * G = Y-0.6992Cr-0.3359Cb
  47. * B = Y+1.7344Cb
  48. */
  49. #define VID_MPR0_BT601 0x0A800000
  50. #define VID_MPR1_BT601 0x0AAF0000
  51. #define VID_MPR2_BT601 0x094E0754
  52. #define VID_MPR3_BT601 0x00000ADD
  53. #define VID_MIN_HD_HEIGHT 720
  54. #define DBGFS_DUMP(reg) seq_printf(s, "\n %-25s 0x%08X", #reg, \
  55. readl(vid->regs + reg))
  56. static void vid_dbg_ctl(struct seq_file *s, int val)
  57. {
  58. val = val >> 30;
  59. seq_putc(s, '\t');
  60. if (!(val & 1))
  61. seq_puts(s, "NOT ");
  62. seq_puts(s, "ignored on main mixer - ");
  63. if (!(val & 2))
  64. seq_puts(s, "NOT ");
  65. seq_puts(s, "ignored on aux mixer");
  66. }
  67. static void vid_dbg_vpo(struct seq_file *s, int val)
  68. {
  69. seq_printf(s, "\txdo:%4d\tydo:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF);
  70. }
  71. static void vid_dbg_vps(struct seq_file *s, int val)
  72. {
  73. seq_printf(s, "\txds:%4d\tyds:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF);
  74. }
  75. static void vid_dbg_mst(struct seq_file *s, int val)
  76. {
  77. if (val & 1)
  78. seq_puts(s, "\tBUFFER UNDERFLOW!");
  79. }
  80. static int vid_dbg_show(struct seq_file *s, void *arg)
  81. {
  82. struct drm_info_node *node = s->private;
  83. struct sti_vid *vid = (struct sti_vid *)node->info_ent->data;
  84. seq_printf(s, "VID: (vaddr= 0x%p)", vid->regs);
  85. DBGFS_DUMP(VID_CTL);
  86. vid_dbg_ctl(s, readl(vid->regs + VID_CTL));
  87. DBGFS_DUMP(VID_ALP);
  88. DBGFS_DUMP(VID_CLF);
  89. DBGFS_DUMP(VID_VPO);
  90. vid_dbg_vpo(s, readl(vid->regs + VID_VPO));
  91. DBGFS_DUMP(VID_VPS);
  92. vid_dbg_vps(s, readl(vid->regs + VID_VPS));
  93. DBGFS_DUMP(VID_KEY1);
  94. DBGFS_DUMP(VID_KEY2);
  95. DBGFS_DUMP(VID_MPR0);
  96. DBGFS_DUMP(VID_MPR1);
  97. DBGFS_DUMP(VID_MPR2);
  98. DBGFS_DUMP(VID_MPR3);
  99. DBGFS_DUMP(VID_MST);
  100. vid_dbg_mst(s, readl(vid->regs + VID_MST));
  101. DBGFS_DUMP(VID_BC);
  102. DBGFS_DUMP(VID_TINT);
  103. DBGFS_DUMP(VID_CSAT);
  104. seq_putc(s, '\n');
  105. return 0;
  106. }
  107. static struct drm_info_list vid_debugfs_files[] = {
  108. { "vid", vid_dbg_show, 0, NULL },
  109. };
  110. void vid_debugfs_init(struct sti_vid *vid, struct drm_minor *minor)
  111. {
  112. unsigned int i;
  113. for (i = 0; i < ARRAY_SIZE(vid_debugfs_files); i++)
  114. vid_debugfs_files[i].data = vid;
  115. drm_debugfs_create_files(vid_debugfs_files,
  116. ARRAY_SIZE(vid_debugfs_files),
  117. minor->debugfs_root, minor);
  118. }
  119. void sti_vid_commit(struct sti_vid *vid,
  120. struct drm_plane_state *state)
  121. {
  122. struct drm_crtc *crtc = state->crtc;
  123. struct drm_display_mode *mode = &crtc->mode;
  124. int dst_x = state->crtc_x;
  125. int dst_y = state->crtc_y;
  126. int dst_w = clamp_val(state->crtc_w, 0, mode->hdisplay - dst_x);
  127. int dst_h = clamp_val(state->crtc_h, 0, mode->vdisplay - dst_y);
  128. int src_h = state->src_h >> 16;
  129. u32 val, ydo, xdo, yds, xds;
  130. /* Input / output size
  131. * Align to upper even value */
  132. dst_w = ALIGN(dst_w, 2);
  133. dst_h = ALIGN(dst_h, 2);
  134. /* Unmask */
  135. val = readl(vid->regs + VID_CTL);
  136. val &= ~VID_CTL_IGNORE;
  137. writel(val, vid->regs + VID_CTL);
  138. ydo = sti_vtg_get_line_number(*mode, dst_y);
  139. yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
  140. xdo = sti_vtg_get_pixel_number(*mode, dst_x);
  141. xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
  142. writel((ydo << 16) | xdo, vid->regs + VID_VPO);
  143. writel((yds << 16) | xds, vid->regs + VID_VPS);
  144. /* Color conversion parameters */
  145. if (src_h >= VID_MIN_HD_HEIGHT) {
  146. writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
  147. writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
  148. writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
  149. writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
  150. } else {
  151. writel(VID_MPR0_BT601, vid->regs + VID_MPR0);
  152. writel(VID_MPR1_BT601, vid->regs + VID_MPR1);
  153. writel(VID_MPR2_BT601, vid->regs + VID_MPR2);
  154. writel(VID_MPR3_BT601, vid->regs + VID_MPR3);
  155. }
  156. }
  157. void sti_vid_disable(struct sti_vid *vid)
  158. {
  159. u32 val;
  160. /* Mask */
  161. val = readl(vid->regs + VID_CTL);
  162. val |= VID_CTL_IGNORE;
  163. writel(val, vid->regs + VID_CTL);
  164. }
  165. static void sti_vid_init(struct sti_vid *vid)
  166. {
  167. /* Enable PSI, Mask layer */
  168. writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
  169. /* Opaque */
  170. writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);
  171. /* Brightness, contrast, tint, saturation */
  172. writel(VID_BC_DFLT, vid->regs + VID_BC);
  173. writel(VID_TINT_DFLT, vid->regs + VID_TINT);
  174. writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
  175. }
  176. struct sti_vid *sti_vid_create(struct device *dev, struct drm_device *drm_dev,
  177. int id, void __iomem *baseaddr)
  178. {
  179. struct sti_vid *vid;
  180. vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
  181. if (!vid) {
  182. DRM_ERROR("Failed to allocate memory for VID\n");
  183. return NULL;
  184. }
  185. vid->dev = dev;
  186. vid->regs = baseaddr;
  187. vid->id = id;
  188. sti_vid_init(vid);
  189. return vid;
  190. }