atmel_hlcdc_plane.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2014 Free Electrons
  4. * Copyright (C) 2014 Atmel
  5. *
  6. * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
  7. */
  8. #include <linux/dmapool.h>
  9. #include <linux/mfd/atmel-hlcdc.h>
  10. #include <drm/drm_atomic.h>
  11. #include <drm/drm_atomic_helper.h>
  12. #include <drm/drm_blend.h>
  13. #include <drm/drm_fb_dma_helper.h>
  14. #include <drm/drm_fourcc.h>
  15. #include <drm/drm_framebuffer.h>
  16. #include <drm/drm_gem_dma_helper.h>
  17. #include "atmel_hlcdc_dc.h"
  18. /**
  19. * struct atmel_hlcdc_plane_state - Atmel HLCDC Plane state structure.
  20. *
  21. * @base: DRM plane state
  22. * @crtc_x: x position of the plane relative to the CRTC
  23. * @crtc_y: y position of the plane relative to the CRTC
  24. * @crtc_w: visible width of the plane
  25. * @crtc_h: visible height of the plane
  26. * @src_x: x buffer position
  27. * @src_y: y buffer position
  28. * @src_w: buffer width
  29. * @src_h: buffer height
  30. * @disc_x: x discard position
  31. * @disc_y: y discard position
  32. * @disc_w: discard width
  33. * @disc_h: discard height
  34. * @ahb_id: AHB identification number
  35. * @bpp: bytes per pixel deduced from pixel_format
  36. * @offsets: offsets to apply to the GEM buffers
  37. * @xstride: value to add to the pixel pointer between each line
  38. * @pstride: value to add to the pixel pointer between each pixel
  39. * @nplanes: number of planes (deduced from pixel_format)
  40. * @dscrs: DMA descriptors
  41. */
  42. struct atmel_hlcdc_plane_state {
  43. struct drm_plane_state base;
  44. int crtc_x;
  45. int crtc_y;
  46. unsigned int crtc_w;
  47. unsigned int crtc_h;
  48. uint32_t src_x;
  49. uint32_t src_y;
  50. uint32_t src_w;
  51. uint32_t src_h;
  52. int disc_x;
  53. int disc_y;
  54. int disc_w;
  55. int disc_h;
  56. int ahb_id;
  57. /* These fields are private and should not be touched */
  58. int bpp[ATMEL_HLCDC_LAYER_MAX_PLANES];
  59. unsigned int offsets[ATMEL_HLCDC_LAYER_MAX_PLANES];
  60. int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
  61. int pstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
  62. int nplanes;
  63. /* DMA descriptors. */
  64. struct atmel_hlcdc_dma_channel_dscr *dscrs[ATMEL_HLCDC_LAYER_MAX_PLANES];
  65. };
  66. static inline struct atmel_hlcdc_plane_state *
  67. drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
  68. {
  69. return container_of(s, struct atmel_hlcdc_plane_state, base);
  70. }
  71. #define SUBPIXEL_MASK 0xffff
  72. static uint32_t rgb_formats[] = {
  73. DRM_FORMAT_C8,
  74. DRM_FORMAT_XRGB4444,
  75. DRM_FORMAT_ARGB4444,
  76. DRM_FORMAT_RGBA4444,
  77. DRM_FORMAT_ARGB1555,
  78. DRM_FORMAT_RGB565,
  79. DRM_FORMAT_RGB888,
  80. DRM_FORMAT_XRGB8888,
  81. DRM_FORMAT_ARGB8888,
  82. DRM_FORMAT_RGBA8888,
  83. };
  84. struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
  85. .formats = rgb_formats,
  86. .nformats = ARRAY_SIZE(rgb_formats),
  87. };
  88. static uint32_t rgb_and_yuv_formats[] = {
  89. DRM_FORMAT_C8,
  90. DRM_FORMAT_XRGB4444,
  91. DRM_FORMAT_ARGB4444,
  92. DRM_FORMAT_RGBA4444,
  93. DRM_FORMAT_ARGB1555,
  94. DRM_FORMAT_RGB565,
  95. DRM_FORMAT_RGB888,
  96. DRM_FORMAT_XRGB8888,
  97. DRM_FORMAT_ARGB8888,
  98. DRM_FORMAT_RGBA8888,
  99. DRM_FORMAT_AYUV,
  100. DRM_FORMAT_YUYV,
  101. DRM_FORMAT_UYVY,
  102. DRM_FORMAT_YVYU,
  103. DRM_FORMAT_VYUY,
  104. DRM_FORMAT_NV21,
  105. DRM_FORMAT_NV61,
  106. DRM_FORMAT_YUV422,
  107. DRM_FORMAT_YUV420,
  108. };
  109. struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
  110. .formats = rgb_and_yuv_formats,
  111. .nformats = ARRAY_SIZE(rgb_and_yuv_formats),
  112. };
  113. static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
  114. {
  115. switch (format) {
  116. case DRM_FORMAT_C8:
  117. *mode = ATMEL_HLCDC_C8_MODE;
  118. break;
  119. case DRM_FORMAT_XRGB4444:
  120. *mode = ATMEL_HLCDC_XRGB4444_MODE;
  121. break;
  122. case DRM_FORMAT_ARGB4444:
  123. *mode = ATMEL_HLCDC_ARGB4444_MODE;
  124. break;
  125. case DRM_FORMAT_RGBA4444:
  126. *mode = ATMEL_HLCDC_RGBA4444_MODE;
  127. break;
  128. case DRM_FORMAT_RGB565:
  129. *mode = ATMEL_HLCDC_RGB565_MODE;
  130. break;
  131. case DRM_FORMAT_RGB888:
  132. *mode = ATMEL_HLCDC_RGB888_MODE;
  133. break;
  134. case DRM_FORMAT_ARGB1555:
  135. *mode = ATMEL_HLCDC_ARGB1555_MODE;
  136. break;
  137. case DRM_FORMAT_XRGB8888:
  138. *mode = ATMEL_HLCDC_XRGB8888_MODE;
  139. break;
  140. case DRM_FORMAT_ARGB8888:
  141. *mode = ATMEL_HLCDC_ARGB8888_MODE;
  142. break;
  143. case DRM_FORMAT_RGBA8888:
  144. *mode = ATMEL_HLCDC_RGBA8888_MODE;
  145. break;
  146. case DRM_FORMAT_AYUV:
  147. *mode = ATMEL_HLCDC_AYUV_MODE;
  148. break;
  149. case DRM_FORMAT_YUYV:
  150. *mode = ATMEL_HLCDC_YUYV_MODE;
  151. break;
  152. case DRM_FORMAT_UYVY:
  153. *mode = ATMEL_HLCDC_UYVY_MODE;
  154. break;
  155. case DRM_FORMAT_YVYU:
  156. *mode = ATMEL_HLCDC_YVYU_MODE;
  157. break;
  158. case DRM_FORMAT_VYUY:
  159. *mode = ATMEL_HLCDC_VYUY_MODE;
  160. break;
  161. case DRM_FORMAT_NV21:
  162. *mode = ATMEL_HLCDC_NV21_MODE;
  163. break;
  164. case DRM_FORMAT_NV61:
  165. *mode = ATMEL_HLCDC_NV61_MODE;
  166. break;
  167. case DRM_FORMAT_YUV420:
  168. *mode = ATMEL_HLCDC_YUV420_MODE;
  169. break;
  170. case DRM_FORMAT_YUV422:
  171. *mode = ATMEL_HLCDC_YUV422_MODE;
  172. break;
  173. default:
  174. return -ENOTSUPP;
  175. }
  176. return 0;
  177. }
  178. static u32 heo_downscaling_xcoef[] = {
  179. 0x11343311,
  180. 0x000000f7,
  181. 0x1635300c,
  182. 0x000000f9,
  183. 0x1b362c08,
  184. 0x000000fb,
  185. 0x1f372804,
  186. 0x000000fe,
  187. 0x24382400,
  188. 0x00000000,
  189. 0x28371ffe,
  190. 0x00000004,
  191. 0x2c361bfb,
  192. 0x00000008,
  193. 0x303516f9,
  194. 0x0000000c,
  195. };
  196. static u32 heo_downscaling_ycoef[] = {
  197. 0x00123737,
  198. 0x00173732,
  199. 0x001b382d,
  200. 0x001f3928,
  201. 0x00243824,
  202. 0x0028391f,
  203. 0x002d381b,
  204. 0x00323717,
  205. };
  206. static u32 heo_upscaling_xcoef[] = {
  207. 0xf74949f7,
  208. 0x00000000,
  209. 0xf55f33fb,
  210. 0x000000fe,
  211. 0xf5701efe,
  212. 0x000000ff,
  213. 0xf87c0dff,
  214. 0x00000000,
  215. 0x00800000,
  216. 0x00000000,
  217. 0x0d7cf800,
  218. 0x000000ff,
  219. 0x1e70f5ff,
  220. 0x000000fe,
  221. 0x335ff5fe,
  222. 0x000000fb,
  223. };
  224. static u32 heo_upscaling_ycoef[] = {
  225. 0x00004040,
  226. 0x00075920,
  227. 0x00056f0c,
  228. 0x00027b03,
  229. 0x00008000,
  230. 0x00037b02,
  231. 0x000c6f05,
  232. 0x00205907,
  233. };
  234. #define ATMEL_HLCDC_XPHIDEF 4
  235. #define ATMEL_HLCDC_YPHIDEF 4
  236. static u32 atmel_hlcdc_plane_phiscaler_get_factor(u32 srcsize,
  237. u32 dstsize,
  238. u32 phidef)
  239. {
  240. u32 factor, max_memsize;
  241. factor = (256 * ((8 * (srcsize - 1)) - phidef)) / (dstsize - 1);
  242. max_memsize = ((factor * (dstsize - 1)) + (256 * phidef)) / 2048;
  243. if (max_memsize > srcsize - 1)
  244. factor--;
  245. return factor;
  246. }
  247. static void
  248. atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
  249. const u32 *coeff_tab, int size,
  250. unsigned int cfg_offs)
  251. {
  252. int i;
  253. for (i = 0; i < size; i++)
  254. atmel_hlcdc_layer_write_cfg(&plane->layer, cfg_offs + i,
  255. coeff_tab[i]);
  256. }
  257. static
  258. void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
  259. struct atmel_hlcdc_plane_state *state)
  260. {
  261. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  262. u32 xfactor, yfactor;
  263. if (!desc->layout.scaler_config)
  264. return;
  265. if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) {
  266. atmel_hlcdc_layer_write_cfg(&plane->layer,
  267. desc->layout.scaler_config, 0);
  268. return;
  269. }
  270. if (desc->layout.phicoeffs.x) {
  271. xfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_w,
  272. state->crtc_w,
  273. ATMEL_HLCDC_XPHIDEF);
  274. yfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_h,
  275. state->crtc_h,
  276. ATMEL_HLCDC_YPHIDEF);
  277. atmel_hlcdc_plane_scaler_set_phicoeff(plane,
  278. state->crtc_w < state->src_w ?
  279. heo_downscaling_xcoef :
  280. heo_upscaling_xcoef,
  281. ARRAY_SIZE(heo_upscaling_xcoef),
  282. desc->layout.phicoeffs.x);
  283. atmel_hlcdc_plane_scaler_set_phicoeff(plane,
  284. state->crtc_h < state->src_h ?
  285. heo_downscaling_ycoef :
  286. heo_upscaling_ycoef,
  287. ARRAY_SIZE(heo_upscaling_ycoef),
  288. desc->layout.phicoeffs.y);
  289. } else {
  290. xfactor = (1024 * state->src_w) / state->crtc_w;
  291. yfactor = (1024 * state->src_h) / state->crtc_h;
  292. }
  293. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config,
  294. ATMEL_HLCDC_LAYER_SCALER_ENABLE |
  295. ATMEL_HLCDC_LAYER_SCALER_FACTORS(xfactor,
  296. yfactor));
  297. }
  298. static
  299. void atmel_xlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
  300. struct atmel_hlcdc_plane_state *state)
  301. {
  302. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  303. u32 xfactor, yfactor;
  304. if (!desc->layout.scaler_config)
  305. return;
  306. if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) {
  307. atmel_hlcdc_layer_write_cfg(&plane->layer,
  308. desc->layout.scaler_config, 0);
  309. return;
  310. }
  311. /* xfactor = round[(2^20 * XMEMSIZE)/XSIZE)] */
  312. xfactor = (u32)(((1 << 20) * state->src_w) / state->crtc_w);
  313. /* yfactor = round[(2^20 * YMEMSIZE)/YSIZE)] */
  314. yfactor = (u32)(((1 << 20) * state->src_h) / state->crtc_h);
  315. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config,
  316. ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE |
  317. ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE |
  318. ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE |
  319. ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE);
  320. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 1,
  321. yfactor);
  322. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 3,
  323. xfactor);
  324. /*
  325. * With YCbCr 4:2:2 and YCbYcr 4:2:0 window resampling, configuration
  326. * register LCDC_HEOCFG25.VXSCFACT and LCDC_HEOCFG27.HXSCFACT is half
  327. * the value of yfactor and xfactor.
  328. */
  329. if (state->base.fb->format->format == DRM_FORMAT_YUV420) {
  330. yfactor /= 2;
  331. xfactor /= 2;
  332. }
  333. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 2,
  334. yfactor);
  335. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 4,
  336. xfactor);
  337. }
  338. static void
  339. atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
  340. struct atmel_hlcdc_plane_state *state)
  341. {
  342. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  343. struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
  344. if (desc->layout.size)
  345. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size,
  346. ATMEL_HLCDC_LAYER_SIZE(state->crtc_w,
  347. state->crtc_h));
  348. if (desc->layout.memsize)
  349. atmel_hlcdc_layer_write_cfg(&plane->layer,
  350. desc->layout.memsize,
  351. ATMEL_HLCDC_LAYER_SIZE(state->src_w,
  352. state->src_h));
  353. if (desc->layout.pos)
  354. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.pos,
  355. ATMEL_HLCDC_LAYER_POS(state->crtc_x,
  356. state->crtc_y));
  357. dc->desc->ops->plane_setup_scaler(plane, state);
  358. }
  359. static
  360. void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
  361. struct atmel_hlcdc_plane_state *state)
  362. {
  363. unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
  364. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  365. const struct drm_format_info *format = state->base.fb->format;
  366. /*
  367. * Rotation optimization is not working on RGB888 (rotation is still
  368. * working but without any optimization).
  369. */
  370. if (format->format == DRM_FORMAT_RGB888)
  371. cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS;
  372. atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG,
  373. cfg);
  374. cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP;
  375. if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
  376. cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
  377. ATMEL_HLCDC_LAYER_ITER;
  378. if (format->has_alpha)
  379. cfg |= ATMEL_HLCDC_LAYER_LAEN;
  380. else
  381. cfg |= ATMEL_HLCDC_LAYER_GAEN |
  382. ATMEL_HLCDC_LAYER_GA(state->base.alpha);
  383. }
  384. if (state->disc_h && state->disc_w)
  385. cfg |= ATMEL_HLCDC_LAYER_DISCEN;
  386. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config,
  387. cfg);
  388. }
  389. static
  390. void atmel_xlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
  391. struct atmel_hlcdc_plane_state *state)
  392. {
  393. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  394. const struct drm_format_info *format = state->base.fb->format;
  395. unsigned int cfg;
  396. atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_XLCDC_LAYER_DMA_CFG,
  397. ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id);
  398. cfg = ATMEL_XLCDC_LAYER_DMA | ATMEL_XLCDC_LAYER_REP;
  399. if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
  400. /*
  401. * Alpha Blending bits specific to SAM9X7 SoC
  402. */
  403. cfg |= ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS |
  404. ATMEL_XLCDC_LAYER_SFACTA_ONE |
  405. ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS |
  406. ATMEL_XLCDC_LAYER_DFACTA_ONE;
  407. if (format->has_alpha)
  408. cfg |= ATMEL_XLCDC_LAYER_A0(0xff);
  409. else
  410. cfg |= ATMEL_XLCDC_LAYER_A0(state->base.alpha);
  411. }
  412. if (state->disc_h && state->disc_w)
  413. cfg |= ATMEL_XLCDC_LAYER_DISCEN;
  414. atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config,
  415. cfg);
  416. }
  417. static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
  418. struct atmel_hlcdc_plane_state *state)
  419. {
  420. u32 cfg;
  421. int ret;
  422. ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->format->format,
  423. &cfg);
  424. if (ret)
  425. return;
  426. if ((state->base.fb->format->format == DRM_FORMAT_YUV422 ||
  427. state->base.fb->format->format == DRM_FORMAT_NV61) &&
  428. drm_rotation_90_or_270(state->base.rotation))
  429. cfg |= ATMEL_HLCDC_YUV422ROT;
  430. atmel_hlcdc_layer_write_cfg(&plane->layer,
  431. ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
  432. }
  433. static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane,
  434. struct atmel_hlcdc_plane_state *state)
  435. {
  436. struct drm_crtc *crtc = state->base.crtc;
  437. struct drm_color_lut *lut;
  438. int idx;
  439. if (!crtc || !crtc->state)
  440. return;
  441. if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
  442. return;
  443. lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
  444. for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
  445. u32 val = ((lut->red << 8) & 0xff0000) |
  446. (lut->green & 0xff00) |
  447. (lut->blue >> 8);
  448. atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
  449. }
  450. }
  451. static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane,
  452. struct atmel_hlcdc_plane_state *state,
  453. u32 sr, int i)
  454. {
  455. atmel_hlcdc_layer_write_reg(&plane->layer,
  456. ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
  457. state->dscrs[i]->self);
  458. if (sr & ATMEL_HLCDC_LAYER_EN)
  459. return;
  460. atmel_hlcdc_layer_write_reg(&plane->layer,
  461. ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
  462. state->dscrs[i]->addr);
  463. atmel_hlcdc_layer_write_reg(&plane->layer,
  464. ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
  465. state->dscrs[i]->ctrl);
  466. atmel_hlcdc_layer_write_reg(&plane->layer,
  467. ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
  468. state->dscrs[i]->self);
  469. }
  470. static void atmel_xlcdc_update_buffers(struct atmel_hlcdc_plane *plane,
  471. struct atmel_hlcdc_plane_state *state,
  472. u32 sr, int i)
  473. {
  474. atmel_hlcdc_layer_write_reg(&plane->layer,
  475. ATMEL_XLCDC_LAYER_PLANE_ADDR(i),
  476. state->dscrs[i]->addr);
  477. }
  478. static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
  479. struct atmel_hlcdc_plane_state *state)
  480. {
  481. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  482. struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
  483. struct drm_framebuffer *fb = state->base.fb;
  484. u32 sr;
  485. int i;
  486. if (!dc->desc->is_xlcdc)
  487. sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
  488. for (i = 0; i < state->nplanes; i++) {
  489. struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
  490. state->dscrs[i]->addr = gem->dma_addr + state->offsets[i];
  491. dc->desc->ops->lcdc_update_buffers(plane, state, sr, i);
  492. if (desc->layout.xstride[i])
  493. atmel_hlcdc_layer_write_cfg(&plane->layer,
  494. desc->layout.xstride[i],
  495. state->xstride[i]);
  496. if (desc->layout.pstride[i])
  497. atmel_hlcdc_layer_write_cfg(&plane->layer,
  498. desc->layout.pstride[i],
  499. state->pstride[i]);
  500. }
  501. }
  502. int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state)
  503. {
  504. unsigned int ahb_load[2] = { };
  505. struct drm_plane *plane;
  506. drm_atomic_crtc_state_for_each_plane(plane, c_state) {
  507. struct atmel_hlcdc_plane_state *plane_state;
  508. struct drm_plane_state *plane_s;
  509. unsigned int pixels, load = 0;
  510. int i;
  511. plane_s = drm_atomic_get_plane_state(c_state->state, plane);
  512. if (IS_ERR(plane_s))
  513. return PTR_ERR(plane_s);
  514. plane_state =
  515. drm_plane_state_to_atmel_hlcdc_plane_state(plane_s);
  516. pixels = (plane_state->src_w * plane_state->src_h) -
  517. (plane_state->disc_w * plane_state->disc_h);
  518. for (i = 0; i < plane_state->nplanes; i++)
  519. load += pixels * plane_state->bpp[i];
  520. if (ahb_load[0] <= ahb_load[1])
  521. plane_state->ahb_id = 0;
  522. else
  523. plane_state->ahb_id = 1;
  524. ahb_load[plane_state->ahb_id] += load;
  525. }
  526. return 0;
  527. }
  528. int
  529. atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
  530. {
  531. int disc_x = 0, disc_y = 0, disc_w = 0, disc_h = 0;
  532. const struct atmel_hlcdc_layer_cfg_layout *layout;
  533. struct atmel_hlcdc_plane_state *primary_state;
  534. struct drm_plane_state *primary_s;
  535. struct atmel_hlcdc_plane *primary;
  536. struct drm_plane *ovl;
  537. primary = drm_plane_to_atmel_hlcdc_plane(c_state->crtc->primary);
  538. layout = &primary->layer.desc->layout;
  539. if (!layout->disc_pos || !layout->disc_size)
  540. return 0;
  541. primary_s = drm_atomic_get_plane_state(c_state->state,
  542. &primary->base);
  543. if (IS_ERR(primary_s))
  544. return PTR_ERR(primary_s);
  545. primary_state = drm_plane_state_to_atmel_hlcdc_plane_state(primary_s);
  546. drm_atomic_crtc_state_for_each_plane(ovl, c_state) {
  547. struct atmel_hlcdc_plane_state *ovl_state;
  548. struct drm_plane_state *ovl_s;
  549. if (ovl == c_state->crtc->primary)
  550. continue;
  551. ovl_s = drm_atomic_get_plane_state(c_state->state, ovl);
  552. if (IS_ERR(ovl_s))
  553. return PTR_ERR(ovl_s);
  554. ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s);
  555. if (!ovl_s->visible ||
  556. !ovl_s->fb ||
  557. ovl_s->fb->format->has_alpha ||
  558. ovl_s->alpha != DRM_BLEND_ALPHA_OPAQUE)
  559. continue;
  560. /* TODO: implement a smarter hidden area detection */
  561. if (ovl_state->crtc_h * ovl_state->crtc_w < disc_h * disc_w)
  562. continue;
  563. disc_x = ovl_state->crtc_x;
  564. disc_y = ovl_state->crtc_y;
  565. disc_h = ovl_state->crtc_h;
  566. disc_w = ovl_state->crtc_w;
  567. }
  568. primary_state->disc_x = disc_x;
  569. primary_state->disc_y = disc_y;
  570. primary_state->disc_w = disc_w;
  571. primary_state->disc_h = disc_h;
  572. return 0;
  573. }
  574. static void
  575. atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane,
  576. struct atmel_hlcdc_plane_state *state)
  577. {
  578. const struct atmel_hlcdc_layer_cfg_layout *layout;
  579. layout = &plane->layer.desc->layout;
  580. if (!layout->disc_pos || !layout->disc_size)
  581. return;
  582. atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_pos,
  583. ATMEL_HLCDC_LAYER_DISC_POS(state->disc_x,
  584. state->disc_y));
  585. atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_size,
  586. ATMEL_HLCDC_LAYER_DISC_SIZE(state->disc_w,
  587. state->disc_h));
  588. }
  589. static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
  590. struct drm_atomic_state *state)
  591. {
  592. struct drm_plane_state *s = drm_atomic_get_new_plane_state(state, p);
  593. struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
  594. struct atmel_hlcdc_plane_state *hstate =
  595. drm_plane_state_to_atmel_hlcdc_plane_state(s);
  596. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  597. struct drm_framebuffer *fb = hstate->base.fb;
  598. const struct drm_display_mode *mode;
  599. struct drm_crtc_state *crtc_state;
  600. int ret;
  601. int i;
  602. if (!hstate->base.crtc || WARN_ON(!fb))
  603. return 0;
  604. crtc_state = drm_atomic_get_existing_crtc_state(state, s->crtc);
  605. mode = &crtc_state->adjusted_mode;
  606. ret = drm_atomic_helper_check_plane_state(s, crtc_state,
  607. (1 << 16) / 2048,
  608. INT_MAX, true, true);
  609. if (ret || !s->visible)
  610. return ret;
  611. hstate->src_x = s->src.x1;
  612. hstate->src_y = s->src.y1;
  613. hstate->src_w = drm_rect_width(&s->src);
  614. hstate->src_h = drm_rect_height(&s->src);
  615. hstate->crtc_x = s->dst.x1;
  616. hstate->crtc_y = s->dst.y1;
  617. hstate->crtc_w = drm_rect_width(&s->dst);
  618. hstate->crtc_h = drm_rect_height(&s->dst);
  619. if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) &
  620. SUBPIXEL_MASK)
  621. return -EINVAL;
  622. hstate->src_x >>= 16;
  623. hstate->src_y >>= 16;
  624. hstate->src_w >>= 16;
  625. hstate->src_h >>= 16;
  626. hstate->nplanes = fb->format->num_planes;
  627. if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)
  628. return -EINVAL;
  629. for (i = 0; i < hstate->nplanes; i++) {
  630. unsigned int offset = 0;
  631. int xdiv = i ? fb->format->hsub : 1;
  632. int ydiv = i ? fb->format->vsub : 1;
  633. hstate->bpp[i] = fb->format->cpp[i];
  634. if (!hstate->bpp[i])
  635. return -EINVAL;
  636. switch (hstate->base.rotation & DRM_MODE_ROTATE_MASK) {
  637. case DRM_MODE_ROTATE_90:
  638. offset = (hstate->src_y / ydiv) *
  639. fb->pitches[i];
  640. offset += ((hstate->src_x + hstate->src_w - 1) /
  641. xdiv) * hstate->bpp[i];
  642. hstate->xstride[i] = -(((hstate->src_h - 1) / ydiv) *
  643. fb->pitches[i]) -
  644. (2 * hstate->bpp[i]);
  645. hstate->pstride[i] = fb->pitches[i] - hstate->bpp[i];
  646. break;
  647. case DRM_MODE_ROTATE_180:
  648. offset = ((hstate->src_y + hstate->src_h - 1) /
  649. ydiv) * fb->pitches[i];
  650. offset += ((hstate->src_x + hstate->src_w - 1) /
  651. xdiv) * hstate->bpp[i];
  652. hstate->xstride[i] = ((((hstate->src_w - 1) / xdiv) - 1) *
  653. hstate->bpp[i]) - fb->pitches[i];
  654. hstate->pstride[i] = -2 * hstate->bpp[i];
  655. break;
  656. case DRM_MODE_ROTATE_270:
  657. offset = ((hstate->src_y + hstate->src_h - 1) /
  658. ydiv) * fb->pitches[i];
  659. offset += (hstate->src_x / xdiv) * hstate->bpp[i];
  660. hstate->xstride[i] = ((hstate->src_h - 1) / ydiv) *
  661. fb->pitches[i];
  662. hstate->pstride[i] = -fb->pitches[i] - hstate->bpp[i];
  663. break;
  664. case DRM_MODE_ROTATE_0:
  665. default:
  666. offset = (hstate->src_y / ydiv) * fb->pitches[i];
  667. offset += (hstate->src_x / xdiv) * hstate->bpp[i];
  668. hstate->xstride[i] = fb->pitches[i] -
  669. ((hstate->src_w / xdiv) *
  670. hstate->bpp[i]);
  671. hstate->pstride[i] = 0;
  672. break;
  673. }
  674. hstate->offsets[i] = offset + fb->offsets[i];
  675. }
  676. /*
  677. * Swap width and size in case of 90 or 270 degrees rotation
  678. */
  679. if (drm_rotation_90_or_270(hstate->base.rotation)) {
  680. swap(hstate->src_w, hstate->src_h);
  681. }
  682. if (!desc->layout.size &&
  683. (mode->hdisplay != hstate->crtc_w ||
  684. mode->vdisplay != hstate->crtc_h))
  685. return -EINVAL;
  686. if ((hstate->crtc_h != hstate->src_h || hstate->crtc_w != hstate->src_w) &&
  687. (!desc->layout.memsize ||
  688. hstate->base.fb->format->has_alpha))
  689. return -EINVAL;
  690. return 0;
  691. }
  692. static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
  693. {
  694. /* Disable interrupts */
  695. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR,
  696. 0xffffffff);
  697. /* Disable the layer */
  698. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHDR,
  699. ATMEL_HLCDC_LAYER_RST |
  700. ATMEL_HLCDC_LAYER_A2Q |
  701. ATMEL_HLCDC_LAYER_UPDATE);
  702. /* Clear all pending interrupts */
  703. atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
  704. }
  705. static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
  706. {
  707. /* Disable interrupts */
  708. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IDR,
  709. 0xffffffff);
  710. /* Disable the layer */
  711. atmel_hlcdc_layer_write_reg(&plane->layer,
  712. ATMEL_XLCDC_LAYER_ENR, 0);
  713. /* Clear all pending interrupts */
  714. atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR);
  715. }
  716. static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
  717. struct drm_atomic_state *state)
  718. {
  719. struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
  720. struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
  721. dc->desc->ops->lcdc_atomic_disable(plane);
  722. }
  723. static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane,
  724. struct atmel_hlcdc_dc *dc)
  725. {
  726. u32 sr;
  727. /* Enable the overrun interrupts. */
  728. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
  729. ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
  730. ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
  731. ATMEL_HLCDC_LAYER_OVR_IRQ(2));
  732. /* Apply the new config at the next SOF event. */
  733. sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
  734. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
  735. ATMEL_HLCDC_LAYER_UPDATE |
  736. (sr & ATMEL_HLCDC_LAYER_EN ?
  737. ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN));
  738. }
  739. static void atmel_xlcdc_atomic_update(struct atmel_hlcdc_plane *plane,
  740. struct atmel_hlcdc_dc *dc)
  741. {
  742. /* Enable the overrun interrupts. */
  743. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IER,
  744. ATMEL_XLCDC_LAYER_OVR_IRQ(0) |
  745. ATMEL_XLCDC_LAYER_OVR_IRQ(1) |
  746. ATMEL_XLCDC_LAYER_OVR_IRQ(2));
  747. atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_ENR,
  748. ATMEL_XLCDC_LAYER_EN);
  749. /*
  750. * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN,
  751. * (where xxx indicates each layer) requires writing one to the
  752. * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7.
  753. */
  754. regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE |
  755. ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE |
  756. ATMEL_XLCDC_HEO_UPDATE);
  757. }
  758. static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
  759. struct drm_atomic_state *state)
  760. {
  761. struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state,
  762. p);
  763. struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
  764. struct atmel_hlcdc_plane_state *hstate =
  765. drm_plane_state_to_atmel_hlcdc_plane_state(new_s);
  766. struct atmel_hlcdc_dc *dc = p->dev->dev_private;
  767. if (!new_s->crtc || !new_s->fb)
  768. return;
  769. if (!hstate->base.visible) {
  770. atmel_hlcdc_plane_atomic_disable(p, state);
  771. return;
  772. }
  773. atmel_hlcdc_plane_update_pos_and_size(plane, hstate);
  774. dc->desc->ops->lcdc_update_general_settings(plane, hstate);
  775. atmel_hlcdc_plane_update_format(plane, hstate);
  776. atmel_hlcdc_plane_update_clut(plane, hstate);
  777. atmel_hlcdc_plane_update_buffers(plane, hstate);
  778. atmel_hlcdc_plane_update_disc_area(plane, hstate);
  779. dc->desc->ops->lcdc_atomic_update(plane, dc);
  780. }
  781. static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane,
  782. const struct atmel_hlcdc_layer_desc *desc)
  783. {
  784. /*
  785. * TODO: declare a "yuv-to-rgb-conv-factors" property to let
  786. * userspace modify these factors (using a BLOB property ?).
  787. */
  788. static const u32 hlcdc_csc_coeffs[] = {
  789. 0x4c900091,
  790. 0x7a5f5090,
  791. 0x40040890
  792. };
  793. for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) {
  794. atmel_hlcdc_layer_write_cfg(&plane->layer,
  795. desc->layout.csc + i,
  796. hlcdc_csc_coeffs[i]);
  797. }
  798. }
  799. static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane,
  800. const struct atmel_hlcdc_layer_desc *desc)
  801. {
  802. /*
  803. * yuv-to-rgb-conv-factors are now defined from LCDC_HEOCFG16 to
  804. * LCDC_HEOCFG21 registers in SAM9X7.
  805. */
  806. static const u32 xlcdc_csc_coeffs[] = {
  807. 0x00000488,
  808. 0x00000648,
  809. 0x1EA00480,
  810. 0x00001D28,
  811. 0x08100480,
  812. 0x00000000,
  813. 0x00000007
  814. };
  815. for (int i = 0; i < ARRAY_SIZE(xlcdc_csc_coeffs); i++) {
  816. atmel_hlcdc_layer_write_cfg(&plane->layer,
  817. desc->layout.csc + i,
  818. xlcdc_csc_coeffs[i]);
  819. }
  820. if (desc->layout.vxs_config && desc->layout.hxs_config) {
  821. /*
  822. * Updating vxs.config and hxs.config fixes the
  823. * Green Color Issue in SAM9X7 EGT Video Player App
  824. */
  825. atmel_hlcdc_layer_write_cfg(&plane->layer,
  826. desc->layout.vxs_config,
  827. ATMEL_XLCDC_LAYER_VXSYCFG_ONE |
  828. ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE |
  829. ATMEL_XLCDC_LAYER_VXSCCFG_ONE |
  830. ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE);
  831. atmel_hlcdc_layer_write_cfg(&plane->layer,
  832. desc->layout.hxs_config,
  833. ATMEL_XLCDC_LAYER_HXSYCFG_ONE |
  834. ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE |
  835. ATMEL_XLCDC_LAYER_HXSCCFG_ONE |
  836. ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE);
  837. }
  838. }
  839. static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
  840. {
  841. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  842. struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
  843. if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
  844. desc->type == ATMEL_HLCDC_CURSOR_LAYER) {
  845. int ret;
  846. ret = drm_plane_create_alpha_property(&plane->base);
  847. if (ret)
  848. return ret;
  849. }
  850. if (desc->layout.xstride[0] && desc->layout.pstride[0]) {
  851. int ret;
  852. ret = drm_plane_create_rotation_property(&plane->base,
  853. DRM_MODE_ROTATE_0,
  854. DRM_MODE_ROTATE_0 |
  855. DRM_MODE_ROTATE_90 |
  856. DRM_MODE_ROTATE_180 |
  857. DRM_MODE_ROTATE_270);
  858. if (ret)
  859. return ret;
  860. }
  861. if (desc->layout.csc)
  862. dc->desc->ops->lcdc_csc_init(plane, desc);
  863. return 0;
  864. }
  865. static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane,
  866. const struct atmel_hlcdc_layer_desc *desc)
  867. {
  868. u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
  869. /*
  870. * There's not much we can do in case of overrun except informing
  871. * the user. However, we are in interrupt context here, hence the
  872. * use of dev_dbg().
  873. */
  874. if (isr &
  875. (ATMEL_HLCDC_LAYER_OVR_IRQ(0) | ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
  876. ATMEL_HLCDC_LAYER_OVR_IRQ(2)))
  877. dev_dbg(plane->base.dev->dev, "overrun on plane %s\n",
  878. desc->name);
  879. }
  880. static void atmel_xlcdc_irq_dbg(struct atmel_hlcdc_plane *plane,
  881. const struct atmel_hlcdc_layer_desc *desc)
  882. {
  883. u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR);
  884. /*
  885. * There's not much we can do in case of overrun except informing
  886. * the user. However, we are in interrupt context here, hence the
  887. * use of dev_dbg().
  888. */
  889. if (isr &
  890. (ATMEL_XLCDC_LAYER_OVR_IRQ(0) | ATMEL_XLCDC_LAYER_OVR_IRQ(1) |
  891. ATMEL_XLCDC_LAYER_OVR_IRQ(2)))
  892. dev_dbg(plane->base.dev->dev, "overrun on plane %s\n",
  893. desc->name);
  894. }
  895. void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
  896. {
  897. const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
  898. struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
  899. dc->desc->ops->lcdc_irq_dbg(plane, desc);
  900. }
  901. const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = {
  902. .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler,
  903. .lcdc_update_buffers = atmel_hlcdc_update_buffers,
  904. .lcdc_atomic_disable = atmel_hlcdc_atomic_disable,
  905. .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings,
  906. .lcdc_atomic_update = atmel_hlcdc_atomic_update,
  907. .lcdc_csc_init = atmel_hlcdc_csc_init,
  908. .lcdc_irq_dbg = atmel_hlcdc_irq_dbg,
  909. };
  910. const struct atmel_lcdc_dc_ops atmel_xlcdc_ops = {
  911. .plane_setup_scaler = atmel_xlcdc_plane_setup_scaler,
  912. .lcdc_update_buffers = atmel_xlcdc_update_buffers,
  913. .lcdc_atomic_disable = atmel_xlcdc_atomic_disable,
  914. .lcdc_update_general_settings = atmel_xlcdc_plane_update_general_settings,
  915. .lcdc_atomic_update = atmel_xlcdc_atomic_update,
  916. .lcdc_csc_init = atmel_xlcdc_csc_init,
  917. .lcdc_irq_dbg = atmel_xlcdc_irq_dbg,
  918. };
  919. static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
  920. .atomic_check = atmel_hlcdc_plane_atomic_check,
  921. .atomic_update = atmel_hlcdc_plane_atomic_update,
  922. .atomic_disable = atmel_hlcdc_plane_atomic_disable,
  923. };
  924. static int atmel_hlcdc_plane_alloc_dscrs(struct drm_plane *p,
  925. struct atmel_hlcdc_plane_state *state)
  926. {
  927. struct atmel_hlcdc_dc *dc = p->dev->dev_private;
  928. int i;
  929. for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
  930. struct atmel_hlcdc_dma_channel_dscr *dscr;
  931. dma_addr_t dscr_dma;
  932. dscr = dma_pool_alloc(dc->dscrpool, GFP_KERNEL, &dscr_dma);
  933. if (!dscr)
  934. goto err;
  935. dscr->addr = 0;
  936. dscr->next = dscr_dma;
  937. dscr->self = dscr_dma;
  938. dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH;
  939. state->dscrs[i] = dscr;
  940. }
  941. return 0;
  942. err:
  943. for (i--; i >= 0; i--) {
  944. dma_pool_free(dc->dscrpool, state->dscrs[i],
  945. state->dscrs[i]->self);
  946. }
  947. return -ENOMEM;
  948. }
  949. static void atmel_hlcdc_plane_reset(struct drm_plane *p)
  950. {
  951. struct atmel_hlcdc_plane_state *state;
  952. if (p->state) {
  953. state = drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
  954. if (state->base.fb)
  955. drm_framebuffer_put(state->base.fb);
  956. kfree(state);
  957. p->state = NULL;
  958. }
  959. state = kzalloc(sizeof(*state), GFP_KERNEL);
  960. if (state) {
  961. if (atmel_hlcdc_plane_alloc_dscrs(p, state)) {
  962. kfree(state);
  963. dev_err(p->dev->dev,
  964. "Failed to allocate initial plane state\n");
  965. return;
  966. }
  967. __drm_atomic_helper_plane_reset(p, &state->base);
  968. }
  969. }
  970. static struct drm_plane_state *
  971. atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
  972. {
  973. struct atmel_hlcdc_plane_state *state =
  974. drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
  975. struct atmel_hlcdc_plane_state *copy;
  976. copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
  977. if (!copy)
  978. return NULL;
  979. if (atmel_hlcdc_plane_alloc_dscrs(p, copy)) {
  980. kfree(copy);
  981. return NULL;
  982. }
  983. if (copy->base.fb)
  984. drm_framebuffer_get(copy->base.fb);
  985. return &copy->base;
  986. }
  987. static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p,
  988. struct drm_plane_state *s)
  989. {
  990. struct atmel_hlcdc_plane_state *state =
  991. drm_plane_state_to_atmel_hlcdc_plane_state(s);
  992. struct atmel_hlcdc_dc *dc = p->dev->dev_private;
  993. int i;
  994. for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
  995. dma_pool_free(dc->dscrpool, state->dscrs[i],
  996. state->dscrs[i]->self);
  997. }
  998. if (s->fb)
  999. drm_framebuffer_put(s->fb);
  1000. kfree(state);
  1001. }
  1002. static const struct drm_plane_funcs layer_plane_funcs = {
  1003. .update_plane = drm_atomic_helper_update_plane,
  1004. .disable_plane = drm_atomic_helper_disable_plane,
  1005. .destroy = drm_plane_cleanup,
  1006. .reset = atmel_hlcdc_plane_reset,
  1007. .atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state,
  1008. .atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state,
  1009. };
  1010. static int atmel_hlcdc_plane_create(struct drm_device *dev,
  1011. const struct atmel_hlcdc_layer_desc *desc)
  1012. {
  1013. struct atmel_hlcdc_dc *dc = dev->dev_private;
  1014. struct atmel_hlcdc_plane *plane;
  1015. enum drm_plane_type type;
  1016. int ret;
  1017. plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
  1018. if (!plane)
  1019. return -ENOMEM;
  1020. atmel_hlcdc_layer_init(&plane->layer, desc, dc->hlcdc->regmap);
  1021. if (desc->type == ATMEL_HLCDC_BASE_LAYER)
  1022. type = DRM_PLANE_TYPE_PRIMARY;
  1023. else if (desc->type == ATMEL_HLCDC_CURSOR_LAYER)
  1024. type = DRM_PLANE_TYPE_CURSOR;
  1025. else
  1026. type = DRM_PLANE_TYPE_OVERLAY;
  1027. ret = drm_universal_plane_init(dev, &plane->base, 0,
  1028. &layer_plane_funcs,
  1029. desc->formats->formats,
  1030. desc->formats->nformats,
  1031. NULL, type, NULL);
  1032. if (ret)
  1033. return ret;
  1034. drm_plane_helper_add(&plane->base,
  1035. &atmel_hlcdc_layer_plane_helper_funcs);
  1036. /* Set default property values*/
  1037. ret = atmel_hlcdc_plane_init_properties(plane);
  1038. if (ret)
  1039. return ret;
  1040. dc->layers[desc->id] = &plane->layer;
  1041. return 0;
  1042. }
  1043. int atmel_hlcdc_create_planes(struct drm_device *dev)
  1044. {
  1045. struct atmel_hlcdc_dc *dc = dev->dev_private;
  1046. const struct atmel_hlcdc_layer_desc *descs = dc->desc->layers;
  1047. int nlayers = dc->desc->nlayers;
  1048. int i, ret;
  1049. dc->dscrpool = dmam_pool_create("atmel-hlcdc-dscr", dev->dev,
  1050. sizeof(struct atmel_hlcdc_dma_channel_dscr),
  1051. sizeof(u64), 0);
  1052. if (!dc->dscrpool)
  1053. return -ENOMEM;
  1054. for (i = 0; i < nlayers; i++) {
  1055. if (descs[i].type != ATMEL_HLCDC_BASE_LAYER &&
  1056. descs[i].type != ATMEL_HLCDC_OVERLAY_LAYER &&
  1057. descs[i].type != ATMEL_HLCDC_CURSOR_LAYER)
  1058. continue;
  1059. ret = atmel_hlcdc_plane_create(dev, &descs[i]);
  1060. if (ret)
  1061. return ret;
  1062. }
  1063. return 0;
  1064. }