dcn10_opp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright 2012-15 Advanced Micro Devices, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Authors: AMD
  23. *
  24. */
  25. #include "dm_services.h"
  26. #include "dcn10_opp.h"
  27. #include "reg_helper.h"
  28. #define REG(reg) \
  29. (oppn10->regs->reg)
  30. #undef FN
  31. #define FN(reg_name, field_name) \
  32. oppn10->opp_shift->field_name, oppn10->opp_mask->field_name
  33. #define CTX \
  34. oppn10->base.ctx
  35. /************* FORMATTER ************/
  36. /**
  37. * set_truncation
  38. * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
  39. * 2) enable truncation
  40. * 3) HW remove 12bit FMT support for DCE11 power saving reason.
  41. */
  42. static void opp1_set_truncation(
  43. struct dcn10_opp *oppn10,
  44. const struct bit_depth_reduction_params *params)
  45. {
  46. REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
  47. FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
  48. FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH,
  49. FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE);
  50. }
  51. static void opp1_set_spatial_dither(
  52. struct dcn10_opp *oppn10,
  53. const struct bit_depth_reduction_params *params)
  54. {
  55. /*Disable spatial (random) dithering*/
  56. REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL,
  57. FMT_SPATIAL_DITHER_EN, 0,
  58. FMT_SPATIAL_DITHER_MODE, 0,
  59. FMT_SPATIAL_DITHER_DEPTH, 0,
  60. FMT_TEMPORAL_DITHER_EN, 0,
  61. FMT_HIGHPASS_RANDOM_ENABLE, 0,
  62. FMT_FRAME_RANDOM_ENABLE, 0,
  63. FMT_RGB_RANDOM_ENABLE, 0);
  64. /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
  65. if (params->flags.FRAME_RANDOM == 1) {
  66. if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
  67. REG_UPDATE_2(FMT_CONTROL,
  68. FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
  69. FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
  70. } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
  71. REG_UPDATE_2(FMT_CONTROL,
  72. FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
  73. FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
  74. } else {
  75. return;
  76. }
  77. } else {
  78. REG_UPDATE_2(FMT_CONTROL,
  79. FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
  80. FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
  81. }
  82. /*Set seed for random values for
  83. * spatial dithering for R,G,B channels*/
  84. REG_SET(FMT_DITHER_RAND_R_SEED, 0,
  85. FMT_RAND_R_SEED, params->r_seed_value);
  86. REG_SET(FMT_DITHER_RAND_G_SEED, 0,
  87. FMT_RAND_G_SEED, params->g_seed_value);
  88. REG_SET(FMT_DITHER_RAND_B_SEED, 0,
  89. FMT_RAND_B_SEED, params->b_seed_value);
  90. /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
  91. * offset for the R/Cr channel, lower 4LSB
  92. * is forced to zeros. Typically set to 0
  93. * RGB and 0x80000 YCbCr.
  94. */
  95. /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
  96. * offset for the G/Y channel, lower 4LSB is
  97. * forced to zeros. Typically set to 0 RGB
  98. * and 0x80000 YCbCr.
  99. */
  100. /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
  101. * offset for the B/Cb channel, lower 4LSB is
  102. * forced to zeros. Typically set to 0 RGB and
  103. * 0x80000 YCbCr.
  104. */
  105. REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL,
  106. /*Enable spatial dithering*/
  107. FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
  108. /* Set spatial dithering mode
  109. * (default is Seed patterrn AAAA...)
  110. */
  111. FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
  112. /*Set spatial dithering bit depth*/
  113. FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
  114. /*Disable High pass filter*/
  115. FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
  116. /*Reset only at startup*/
  117. FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
  118. /*Set RGB data dithered with x^28+x^3+1*/
  119. FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
  120. }
  121. void opp1_program_bit_depth_reduction(
  122. struct output_pixel_processor *opp,
  123. const struct bit_depth_reduction_params *params)
  124. {
  125. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  126. opp1_set_truncation(oppn10, params);
  127. opp1_set_spatial_dither(oppn10, params);
  128. /* TODO
  129. * set_temporal_dither(oppn10, params);
  130. */
  131. }
  132. /**
  133. * set_pixel_encoding
  134. *
  135. * Set Pixel Encoding
  136. * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
  137. * 1: YCbCr 4:2:2
  138. */
  139. static void opp1_set_pixel_encoding(
  140. struct dcn10_opp *oppn10,
  141. const struct clamping_and_pixel_encoding_params *params)
  142. {
  143. switch (params->pixel_encoding) {
  144. case PIXEL_ENCODING_RGB:
  145. case PIXEL_ENCODING_YCBCR444:
  146. REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0);
  147. break;
  148. case PIXEL_ENCODING_YCBCR422:
  149. REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 1);
  150. break;
  151. case PIXEL_ENCODING_YCBCR420:
  152. REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2);
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. /**
  159. * Set Clamping
  160. * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
  161. * 1 for 8 bpc
  162. * 2 for 10 bpc
  163. * 3 for 12 bpc
  164. * 7 for programable
  165. * 2) Enable clamp if Limited range requested
  166. */
  167. static void opp1_set_clamping(
  168. struct dcn10_opp *oppn10,
  169. const struct clamping_and_pixel_encoding_params *params)
  170. {
  171. REG_UPDATE_2(FMT_CLAMP_CNTL,
  172. FMT_CLAMP_DATA_EN, 0,
  173. FMT_CLAMP_COLOR_FORMAT, 0);
  174. switch (params->clamping_level) {
  175. case CLAMPING_FULL_RANGE:
  176. REG_UPDATE_2(FMT_CLAMP_CNTL,
  177. FMT_CLAMP_DATA_EN, 1,
  178. FMT_CLAMP_COLOR_FORMAT, 0);
  179. break;
  180. case CLAMPING_LIMITED_RANGE_8BPC:
  181. REG_UPDATE_2(FMT_CLAMP_CNTL,
  182. FMT_CLAMP_DATA_EN, 1,
  183. FMT_CLAMP_COLOR_FORMAT, 1);
  184. break;
  185. case CLAMPING_LIMITED_RANGE_10BPC:
  186. REG_UPDATE_2(FMT_CLAMP_CNTL,
  187. FMT_CLAMP_DATA_EN, 1,
  188. FMT_CLAMP_COLOR_FORMAT, 2);
  189. break;
  190. case CLAMPING_LIMITED_RANGE_12BPC:
  191. REG_UPDATE_2(FMT_CLAMP_CNTL,
  192. FMT_CLAMP_DATA_EN, 1,
  193. FMT_CLAMP_COLOR_FORMAT, 3);
  194. break;
  195. case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
  196. /* TODO */
  197. default:
  198. break;
  199. }
  200. }
  201. void opp1_set_dyn_expansion(
  202. struct output_pixel_processor *opp,
  203. enum dc_color_space color_sp,
  204. enum dc_color_depth color_dpth,
  205. enum signal_type signal)
  206. {
  207. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  208. REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
  209. FMT_DYNAMIC_EXP_EN, 0,
  210. FMT_DYNAMIC_EXP_MODE, 0);
  211. /*00 - 10-bit -> 12-bit dynamic expansion*/
  212. /*01 - 8-bit -> 12-bit dynamic expansion*/
  213. if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
  214. signal == SIGNAL_TYPE_DISPLAY_PORT ||
  215. signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
  216. signal == SIGNAL_TYPE_VIRTUAL) {
  217. switch (color_dpth) {
  218. case COLOR_DEPTH_888:
  219. REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
  220. FMT_DYNAMIC_EXP_EN, 1,
  221. FMT_DYNAMIC_EXP_MODE, 1);
  222. break;
  223. case COLOR_DEPTH_101010:
  224. REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
  225. FMT_DYNAMIC_EXP_EN, 1,
  226. FMT_DYNAMIC_EXP_MODE, 0);
  227. break;
  228. case COLOR_DEPTH_121212:
  229. REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
  230. FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
  231. FMT_DYNAMIC_EXP_MODE, 0);
  232. break;
  233. default:
  234. break;
  235. }
  236. }
  237. }
  238. static void opp1_program_clamping_and_pixel_encoding(
  239. struct output_pixel_processor *opp,
  240. const struct clamping_and_pixel_encoding_params *params)
  241. {
  242. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  243. opp1_set_clamping(oppn10, params);
  244. opp1_set_pixel_encoding(oppn10, params);
  245. }
  246. void opp1_program_fmt(
  247. struct output_pixel_processor *opp,
  248. struct bit_depth_reduction_params *fmt_bit_depth,
  249. struct clamping_and_pixel_encoding_params *clamping)
  250. {
  251. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  252. if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
  253. REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0);
  254. /* dithering is affected by <CrtcSourceSelect>, hence should be
  255. * programmed afterwards */
  256. opp1_program_bit_depth_reduction(
  257. opp,
  258. fmt_bit_depth);
  259. opp1_program_clamping_and_pixel_encoding(
  260. opp,
  261. clamping);
  262. return;
  263. }
  264. void opp1_program_stereo(
  265. struct output_pixel_processor *opp,
  266. bool enable,
  267. const struct dc_crtc_timing *timing)
  268. {
  269. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  270. uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right;
  271. uint32_t space1_size = timing->v_total - timing->v_addressable;
  272. /* TODO: confirm computation of space2_size */
  273. uint32_t space2_size = timing->v_total - timing->v_addressable;
  274. if (!enable) {
  275. active_width = 0;
  276. space1_size = 0;
  277. space2_size = 0;
  278. }
  279. /* TODO: for which cases should FMT_STEREOSYNC_OVERRIDE be set? */
  280. REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0);
  281. REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width);
  282. /* Program OPPBUF_3D_VACT_SPACE1_SIZE and OPPBUF_VACT_SPACE2_SIZE registers
  283. * In 3D progressive frames, Vactive space happens only in between the 2 frames,
  284. * so only need to program OPPBUF_3D_VACT_SPACE1_SIZE
  285. * In 3D alternative frames, left and right frames, top and bottom field.
  286. */
  287. if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE)
  288. REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size);
  289. else
  290. REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
  291. /* TODO: Is programming of OPPBUF_DUMMY_DATA_R/G/B needed? */
  292. /*
  293. REG_UPDATE(OPPBUF_3D_PARAMETERS_0,
  294. OPPBUF_DUMMY_DATA_R, data_r);
  295. REG_UPDATE(OPPBUF_3D_PARAMETERS_1,
  296. OPPBUF_DUMMY_DATA_G, data_g);
  297. REG_UPDATE(OPPBUF_3D_PARAMETERS_1,
  298. OPPBUF_DUMMY_DATA_B, _data_b);
  299. */
  300. }
  301. void opp1_program_oppbuf(
  302. struct output_pixel_processor *opp,
  303. struct oppbuf_params *oppbuf)
  304. {
  305. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  306. /* Program the oppbuf active width to be the frame width from mpc */
  307. REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, oppbuf->active_width);
  308. /* Specifies the number of segments in multi-segment mode (DP-MSO operation)
  309. * description "In 1/2/4 segment mode, specifies the horizontal active width in pixels of the display panel.
  310. * In 4 segment split left/right mode, specifies the horizontal 1/2 active width in pixels of the display panel.
  311. * Used to determine segment boundaries in multi-segment mode. Used to determine the width of the vertical active space in 3D frame packed modes.
  312. * OPPBUF_ACTIVE_WIDTH must be integer divisible by the total number of segments."
  313. */
  314. REG_UPDATE(OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, oppbuf->mso_segmentation);
  315. /* description "Specifies the number of overlap pixels (1-8 overlapping pixels supported), used in multi-segment mode (DP-MSO operation)" */
  316. REG_UPDATE(OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, oppbuf->mso_overlap_pixel_num);
  317. /* description "Specifies the number of times a pixel is replicated (0-15 pixel replications supported).
  318. * A value of 0 disables replication. The total number of times a pixel is output is OPPBUF_PIXEL_REPETITION + 1."
  319. */
  320. REG_UPDATE(OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, oppbuf->pixel_repetition);
  321. }
  322. void opp1_pipe_clock_control(struct output_pixel_processor *opp, bool enable)
  323. {
  324. struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
  325. uint32_t regval = enable ? 1 : 0;
  326. REG_UPDATE(OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, regval);
  327. }
  328. /*****************************************/
  329. /* Constructor, Destructor */
  330. /*****************************************/
  331. void opp1_destroy(struct output_pixel_processor **opp)
  332. {
  333. kfree(TO_DCN10_OPP(*opp));
  334. *opp = NULL;
  335. }
  336. static struct opp_funcs dcn10_opp_funcs = {
  337. .opp_set_dyn_expansion = opp1_set_dyn_expansion,
  338. .opp_program_fmt = opp1_program_fmt,
  339. .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
  340. .opp_program_stereo = opp1_program_stereo,
  341. .opp_pipe_clock_control = opp1_pipe_clock_control,
  342. .opp_destroy = opp1_destroy
  343. };
  344. void dcn10_opp_construct(struct dcn10_opp *oppn10,
  345. struct dc_context *ctx,
  346. uint32_t inst,
  347. const struct dcn10_opp_registers *regs,
  348. const struct dcn10_opp_shift *opp_shift,
  349. const struct dcn10_opp_mask *opp_mask)
  350. {
  351. oppn10->base.ctx = ctx;
  352. oppn10->base.inst = inst;
  353. oppn10->base.funcs = &dcn10_opp_funcs;
  354. oppn10->regs = regs;
  355. oppn10->opp_shift = opp_shift;
  356. oppn10->opp_mask = opp_mask;
  357. }