dcss-ss.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 NXP.
  4. */
  5. #include <linux/device.h>
  6. #include <linux/slab.h>
  7. #include "dcss-dev.h"
  8. #define DCSS_SS_SYS_CTRL 0x00
  9. #define RUN_EN BIT(0)
  10. #define DCSS_SS_DISPLAY 0x10
  11. #define LRC_X_POS 0
  12. #define LRC_X_MASK GENMASK(12, 0)
  13. #define LRC_Y_POS 16
  14. #define LRC_Y_MASK GENMASK(28, 16)
  15. #define DCSS_SS_HSYNC 0x20
  16. #define DCSS_SS_VSYNC 0x30
  17. #define SYNC_START_POS 0
  18. #define SYNC_START_MASK GENMASK(12, 0)
  19. #define SYNC_END_POS 16
  20. #define SYNC_END_MASK GENMASK(28, 16)
  21. #define SYNC_POL BIT(31)
  22. #define DCSS_SS_DE_ULC 0x40
  23. #define ULC_X_POS 0
  24. #define ULC_X_MASK GENMASK(12, 0)
  25. #define ULC_Y_POS 16
  26. #define ULC_Y_MASK GENMASK(28, 16)
  27. #define ULC_POL BIT(31)
  28. #define DCSS_SS_DE_LRC 0x50
  29. #define DCSS_SS_MODE 0x60
  30. #define PIPE_MODE_POS 0
  31. #define PIPE_MODE_MASK GENMASK(1, 0)
  32. #define DCSS_SS_COEFF 0x70
  33. #define HORIZ_A_POS 0
  34. #define HORIZ_A_MASK GENMASK(3, 0)
  35. #define HORIZ_B_POS 4
  36. #define HORIZ_B_MASK GENMASK(7, 4)
  37. #define HORIZ_C_POS 8
  38. #define HORIZ_C_MASK GENMASK(11, 8)
  39. #define HORIZ_H_NORM_POS 12
  40. #define HORIZ_H_NORM_MASK GENMASK(14, 12)
  41. #define VERT_A_POS 16
  42. #define VERT_A_MASK GENMASK(19, 16)
  43. #define VERT_B_POS 20
  44. #define VERT_B_MASK GENMASK(23, 20)
  45. #define VERT_C_POS 24
  46. #define VERT_C_MASK GENMASK(27, 24)
  47. #define VERT_H_NORM_POS 28
  48. #define VERT_H_NORM_MASK GENMASK(30, 28)
  49. #define DCSS_SS_CLIP_CB 0x80
  50. #define DCSS_SS_CLIP_CR 0x90
  51. #define CLIP_MIN_POS 0
  52. #define CLIP_MIN_MASK GENMASK(9, 0)
  53. #define CLIP_MAX_POS 0
  54. #define CLIP_MAX_MASK GENMASK(23, 16)
  55. #define DCSS_SS_INTER_MODE 0xA0
  56. #define INT_EN BIT(0)
  57. #define VSYNC_SHIFT BIT(1)
  58. struct dcss_ss {
  59. struct device *dev;
  60. void __iomem *base_reg;
  61. u32 base_ofs;
  62. struct dcss_ctxld *ctxld;
  63. u32 ctx_id;
  64. bool in_use;
  65. };
  66. static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs)
  67. {
  68. if (!ss->in_use)
  69. dcss_writel(val, ss->base_reg + ofs);
  70. dcss_ctxld_write(ss->ctxld, ss->ctx_id, val,
  71. ss->base_ofs + ofs);
  72. }
  73. int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
  74. {
  75. struct dcss_ss *ss;
  76. ss = kzalloc(sizeof(*ss), GFP_KERNEL);
  77. if (!ss)
  78. return -ENOMEM;
  79. dcss->ss = ss;
  80. ss->dev = dcss->dev;
  81. ss->ctxld = dcss->ctxld;
  82. ss->base_reg = ioremap(ss_base, SZ_4K);
  83. if (!ss->base_reg) {
  84. dev_err(dcss->dev, "ss: unable to remap ss base\n");
  85. kfree(ss);
  86. return -ENOMEM;
  87. }
  88. ss->base_ofs = ss_base;
  89. ss->ctx_id = CTX_SB_HP;
  90. return 0;
  91. }
  92. void dcss_ss_exit(struct dcss_ss *ss)
  93. {
  94. /* stop SS */
  95. dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
  96. if (ss->base_reg)
  97. iounmap(ss->base_reg);
  98. kfree(ss);
  99. }
  100. void dcss_ss_subsam_set(struct dcss_ss *ss)
  101. {
  102. dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF);
  103. dcss_ss_write(ss, 0, DCSS_SS_MODE);
  104. dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB);
  105. dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR);
  106. }
  107. void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,
  108. bool phsync, bool pvsync)
  109. {
  110. u16 lrc_x, lrc_y;
  111. u16 hsync_start, hsync_end;
  112. u16 vsync_start, vsync_end;
  113. u16 de_ulc_x, de_ulc_y;
  114. u16 de_lrc_x, de_lrc_y;
  115. lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
  116. vm->hactive - 1;
  117. lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
  118. vm->vactive - 1;
  119. dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);
  120. hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
  121. vm->hactive - 1;
  122. hsync_end = vm->hsync_len - 1;
  123. dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |
  124. ((u32)hsync_end << SYNC_END_POS) | hsync_start,
  125. DCSS_SS_HSYNC);
  126. vsync_start = vm->vfront_porch - 1;
  127. vsync_end = vm->vfront_porch + vm->vsync_len - 1;
  128. dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |
  129. ((u32)vsync_end << SYNC_END_POS) | vsync_start,
  130. DCSS_SS_VSYNC);
  131. de_ulc_x = vm->hsync_len + vm->hback_porch - 1;
  132. de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;
  133. dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,
  134. DCSS_SS_DE_ULC);
  135. de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
  136. de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
  137. vm->vactive - 1;
  138. dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);
  139. }
  140. void dcss_ss_enable(struct dcss_ss *ss)
  141. {
  142. dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);
  143. ss->in_use = true;
  144. }
  145. void dcss_ss_shutoff(struct dcss_ss *ss)
  146. {
  147. dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
  148. ss->in_use = false;
  149. }