malidp_hw.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. /*
  2. * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
  3. * Author: Liviu Dudau <Liviu.Dudau@arm.com>
  4. *
  5. * This program is free software and is provided to you under the terms of the
  6. * GNU General Public License version 2 as published by the Free Software
  7. * Foundation, and any use by you of this program is subject to the terms
  8. * of such GNU licence.
  9. *
  10. * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
  11. * the difference between various versions of the hardware is being dealt with
  12. * in an attempt to provide to the rest of the driver code a unified view
  13. */
  14. #include <linux/clk.h>
  15. #include <linux/types.h>
  16. #include <linux/io.h>
  17. #include <drm/drmP.h>
  18. #include <video/videomode.h>
  19. #include <video/display_timing.h>
  20. #include "malidp_drv.h"
  21. #include "malidp_hw.h"
  22. #include "malidp_mw.h"
  23. enum {
  24. MW_NOT_ENABLED = 0, /* SE writeback not enabled */
  25. MW_ONESHOT, /* SE in one-shot mode for writeback */
  26. MW_START, /* SE started writeback */
  27. MW_RESTART, /* SE will start another writeback after this one */
  28. MW_STOP, /* SE needs to stop after this writeback */
  29. };
  30. static const struct malidp_format_id malidp500_de_formats[] = {
  31. /* fourcc, layers supporting the format, internal id */
  32. { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 0 },
  33. { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 1 },
  34. { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 2 },
  35. { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 3 },
  36. { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 4 },
  37. { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 5 },
  38. { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 6 },
  39. { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 7 },
  40. { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 8 },
  41. { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 9 },
  42. { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
  43. { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
  44. { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
  45. { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
  46. { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
  47. { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
  48. };
  49. #define MALIDP_ID(__group, __format) \
  50. ((((__group) & 0x7) << 3) | ((__format) & 0x7))
  51. #define MALIDP_COMMON_FORMATS \
  52. /* fourcc, layers supporting the format, internal id */ \
  53. { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
  54. { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
  55. { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
  56. { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
  57. { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
  58. { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
  59. { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
  60. { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
  61. { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
  62. { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
  63. { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
  64. { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
  65. { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
  66. { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
  67. { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
  68. { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
  69. { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
  70. { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
  71. { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
  72. { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
  73. { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
  74. { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }
  75. static const struct malidp_format_id malidp550_de_formats[] = {
  76. MALIDP_COMMON_FORMATS,
  77. };
  78. static const struct malidp_layer malidp500_layers[] = {
  79. { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
  80. { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
  81. { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
  82. };
  83. static const struct malidp_layer malidp550_layers[] = {
  84. { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
  85. { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
  86. { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
  87. { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 },
  88. };
  89. #define SE_N_SCALING_COEFFS 96
  90. static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
  91. [MALIDP_UPSCALING_COEFFS - 1] = {
  92. 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
  93. 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
  94. 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
  95. 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
  96. 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
  97. 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
  98. 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
  99. 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
  100. 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
  101. 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
  102. 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
  103. 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
  104. },
  105. [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
  106. 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
  107. 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
  108. 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
  109. 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
  110. 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
  111. 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
  112. 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
  113. 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
  114. 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
  115. 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
  116. 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
  117. 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
  118. },
  119. [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
  120. 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
  121. 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
  122. 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
  123. 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
  124. 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
  125. 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
  126. 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
  127. 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
  128. 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
  129. 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
  130. 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
  131. 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
  132. },
  133. [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
  134. 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
  135. 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
  136. 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
  137. 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
  138. 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
  139. 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
  140. 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
  141. 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
  142. 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
  143. 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
  144. 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
  145. 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
  146. },
  147. [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
  148. 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
  149. 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
  150. 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
  151. 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
  152. 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
  153. 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
  154. 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
  155. 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
  156. 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
  157. 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
  158. 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
  159. 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
  160. },
  161. };
  162. #define MALIDP_DE_DEFAULT_PREFETCH_START 5
  163. static int malidp500_query_hw(struct malidp_hw_device *hwdev)
  164. {
  165. u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
  166. /* bit 4 of the CONFIG_ID register holds the line size multiplier */
  167. u8 ln_size_mult = conf & 0x10 ? 2 : 1;
  168. hwdev->min_line_size = 2;
  169. hwdev->max_line_size = SZ_2K * ln_size_mult;
  170. hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
  171. hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
  172. return 0;
  173. }
  174. static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
  175. {
  176. u32 status, count = 100;
  177. malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
  178. while (count) {
  179. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  180. if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
  181. break;
  182. /*
  183. * entering config mode can take as long as the rendering
  184. * of a full frame, hence the long sleep here
  185. */
  186. usleep_range(1000, 10000);
  187. count--;
  188. }
  189. WARN(count == 0, "timeout while entering config mode");
  190. }
  191. static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
  192. {
  193. u32 status, count = 100;
  194. malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
  195. malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
  196. while (count) {
  197. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  198. if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
  199. break;
  200. usleep_range(100, 1000);
  201. count--;
  202. }
  203. WARN(count == 0, "timeout while leaving config mode");
  204. }
  205. static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
  206. {
  207. u32 status;
  208. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  209. if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
  210. return true;
  211. return false;
  212. }
  213. static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
  214. {
  215. if (value)
  216. malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
  217. else
  218. malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
  219. }
  220. static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
  221. {
  222. u32 val = 0;
  223. malidp_hw_write(hwdev, hwdev->output_color_depth,
  224. hwdev->hw->map.out_depth_base);
  225. malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
  226. if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  227. val |= MALIDP500_HSYNCPOL;
  228. if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
  229. val |= MALIDP500_VSYNCPOL;
  230. val |= MALIDP_DE_DEFAULT_PREFETCH_START;
  231. malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
  232. /*
  233. * Mali-DP500 encodes the background color like this:
  234. * - red @ MALIDP500_BGND_COLOR[12:0]
  235. * - green @ MALIDP500_BGND_COLOR[27:16]
  236. * - blue @ (MALIDP500_BGND_COLOR + 4)[12:0]
  237. */
  238. val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
  239. (MALIDP_BGND_COLOR_R & 0xfff);
  240. malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
  241. malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
  242. val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
  243. MALIDP_DE_H_BACKPORCH(mode->hback_porch);
  244. malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
  245. val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
  246. MALIDP_DE_V_BACKPORCH(mode->vback_porch);
  247. malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
  248. val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
  249. MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
  250. malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
  251. val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
  252. malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
  253. if (mode->flags & DISPLAY_FLAGS_INTERLACED)
  254. malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
  255. else
  256. malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
  257. }
  258. static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
  259. {
  260. /* RGB888 or BGR888 can't be rotated */
  261. if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
  262. return -EINVAL;
  263. /*
  264. * Each layer needs enough rotation memory to fit 8 lines
  265. * worth of pixel data. Required size is then:
  266. * size = rotated_width * (bpp / 8) * 8;
  267. */
  268. return w * drm_format_plane_cpp(fmt, 0) * 8;
  269. }
  270. static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
  271. u32 direction,
  272. u16 addr,
  273. u8 coeffs_id)
  274. {
  275. int i;
  276. u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
  277. malidp_hw_write(hwdev,
  278. direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
  279. scaling_control + MALIDP_SE_COEFFTAB_ADDR);
  280. for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
  281. malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
  282. dp500_se_scaling_coeffs[coeffs_id][i]),
  283. scaling_control + MALIDP_SE_COEFFTAB_DATA);
  284. }
  285. static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
  286. struct malidp_se_config *se_config,
  287. struct malidp_se_config *old_config)
  288. {
  289. /* Get array indices into dp500_se_scaling_coeffs. */
  290. u8 h = (u8)se_config->hcoeff - 1;
  291. u8 v = (u8)se_config->vcoeff - 1;
  292. if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
  293. v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
  294. return -EINVAL;
  295. if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
  296. se_config->vcoeff != old_config->vcoeff)) {
  297. malidp500_se_write_pp_coefftab(hwdev,
  298. (MALIDP_SE_V_COEFFTAB |
  299. MALIDP_SE_H_COEFFTAB),
  300. 0, v);
  301. } else {
  302. if (se_config->vcoeff != old_config->vcoeff)
  303. malidp500_se_write_pp_coefftab(hwdev,
  304. MALIDP_SE_V_COEFFTAB,
  305. 0, v);
  306. if (se_config->hcoeff != old_config->hcoeff)
  307. malidp500_se_write_pp_coefftab(hwdev,
  308. MALIDP_SE_H_COEFFTAB,
  309. 0, h);
  310. }
  311. return 0;
  312. }
  313. static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
  314. struct malidp_se_config *se_config,
  315. struct videomode *vm)
  316. {
  317. unsigned long mclk;
  318. unsigned long pxlclk = vm->pixelclock; /* Hz */
  319. unsigned long htotal = vm->hactive + vm->hfront_porch +
  320. vm->hback_porch + vm->hsync_len;
  321. unsigned long input_size = se_config->input_w * se_config->input_h;
  322. unsigned long a = 10;
  323. long ret;
  324. /*
  325. * mclk = max(a, 1.5) * pxlclk
  326. *
  327. * To avoid float calculaiton, using 15 instead of 1.5 and div by
  328. * 10 to get mclk.
  329. */
  330. if (se_config->scale_enable) {
  331. a = 15 * input_size / (htotal * se_config->output_h);
  332. if (a < 15)
  333. a = 15;
  334. }
  335. mclk = a * pxlclk / 10;
  336. ret = clk_get_rate(hwdev->mclk);
  337. if (ret < mclk) {
  338. DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
  339. mclk / 1000);
  340. return -EINVAL;
  341. }
  342. return ret;
  343. }
  344. static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
  345. dma_addr_t *addrs, s32 *pitches,
  346. int num_planes, u16 w, u16 h, u32 fmt_id,
  347. const s16 *rgb2yuv_coeffs)
  348. {
  349. u32 base = MALIDP500_SE_MEMWRITE_BASE;
  350. u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
  351. /* enable the scaling engine block */
  352. malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
  353. /* restart the writeback if already enabled */
  354. if (hwdev->mw_state != MW_NOT_ENABLED)
  355. hwdev->mw_state = MW_RESTART;
  356. else
  357. hwdev->mw_state = MW_START;
  358. malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
  359. switch (num_planes) {
  360. case 2:
  361. malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
  362. malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
  363. malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
  364. /* fall through */
  365. case 1:
  366. malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
  367. malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
  368. malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
  369. break;
  370. default:
  371. WARN(1, "Invalid number of planes");
  372. }
  373. malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
  374. MALIDP500_SE_MEMWRITE_OUT_SIZE);
  375. if (rgb2yuv_coeffs) {
  376. int i;
  377. for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
  378. malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
  379. MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
  380. }
  381. }
  382. malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
  383. return 0;
  384. }
  385. static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
  386. {
  387. u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
  388. if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
  389. hwdev->mw_state = MW_STOP;
  390. malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
  391. malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
  392. }
  393. static int malidp550_query_hw(struct malidp_hw_device *hwdev)
  394. {
  395. u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
  396. u8 ln_size = (conf >> 4) & 0x3, rsize;
  397. hwdev->min_line_size = 2;
  398. switch (ln_size) {
  399. case 0:
  400. hwdev->max_line_size = SZ_2K;
  401. /* two banks of 64KB for rotation memory */
  402. rsize = 64;
  403. break;
  404. case 1:
  405. hwdev->max_line_size = SZ_4K;
  406. /* two banks of 128KB for rotation memory */
  407. rsize = 128;
  408. break;
  409. case 2:
  410. hwdev->max_line_size = 1280;
  411. /* two banks of 40KB for rotation memory */
  412. rsize = 40;
  413. break;
  414. case 3:
  415. /* reserved value */
  416. hwdev->max_line_size = 0;
  417. return -EINVAL;
  418. }
  419. hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
  420. return 0;
  421. }
  422. static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
  423. {
  424. u32 status, count = 100;
  425. malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
  426. while (count) {
  427. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  428. if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
  429. break;
  430. /*
  431. * entering config mode can take as long as the rendering
  432. * of a full frame, hence the long sleep here
  433. */
  434. usleep_range(1000, 10000);
  435. count--;
  436. }
  437. WARN(count == 0, "timeout while entering config mode");
  438. }
  439. static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
  440. {
  441. u32 status, count = 100;
  442. malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
  443. malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
  444. while (count) {
  445. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  446. if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
  447. break;
  448. usleep_range(100, 1000);
  449. count--;
  450. }
  451. WARN(count == 0, "timeout while leaving config mode");
  452. }
  453. static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
  454. {
  455. u32 status;
  456. status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
  457. if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
  458. return true;
  459. return false;
  460. }
  461. static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
  462. {
  463. if (value)
  464. malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
  465. else
  466. malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
  467. }
  468. static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
  469. {
  470. u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
  471. malidp_hw_write(hwdev, hwdev->output_color_depth,
  472. hwdev->hw->map.out_depth_base);
  473. malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
  474. /*
  475. * Mali-DP550 and Mali-DP650 encode the background color like this:
  476. * - red @ MALIDP550_DE_BGND_COLOR[23:16]
  477. * - green @ MALIDP550_DE_BGND_COLOR[15:8]
  478. * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
  479. *
  480. * We need to truncate the least significant 4 bits from the default
  481. * MALIDP_BGND_COLOR_x values
  482. */
  483. val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
  484. (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
  485. ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
  486. malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
  487. val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
  488. MALIDP_DE_H_BACKPORCH(mode->hback_porch);
  489. malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
  490. val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
  491. MALIDP_DE_V_BACKPORCH(mode->vback_porch);
  492. malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
  493. val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
  494. MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
  495. if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  496. val |= MALIDP550_HSYNCPOL;
  497. if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
  498. val |= MALIDP550_VSYNCPOL;
  499. malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
  500. val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
  501. malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
  502. if (mode->flags & DISPLAY_FLAGS_INTERLACED)
  503. malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
  504. else
  505. malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
  506. }
  507. static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
  508. {
  509. u32 bytes_per_col;
  510. /* raw RGB888 or BGR888 can't be rotated */
  511. if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
  512. return -EINVAL;
  513. switch (fmt) {
  514. /* 8 lines at 4 bytes per pixel */
  515. case DRM_FORMAT_ARGB2101010:
  516. case DRM_FORMAT_ABGR2101010:
  517. case DRM_FORMAT_RGBA1010102:
  518. case DRM_FORMAT_BGRA1010102:
  519. case DRM_FORMAT_ARGB8888:
  520. case DRM_FORMAT_ABGR8888:
  521. case DRM_FORMAT_RGBA8888:
  522. case DRM_FORMAT_BGRA8888:
  523. case DRM_FORMAT_XRGB8888:
  524. case DRM_FORMAT_XBGR8888:
  525. case DRM_FORMAT_RGBX8888:
  526. case DRM_FORMAT_BGRX8888:
  527. case DRM_FORMAT_RGB888:
  528. case DRM_FORMAT_BGR888:
  529. /* 16 lines at 2 bytes per pixel */
  530. case DRM_FORMAT_RGBA5551:
  531. case DRM_FORMAT_ABGR1555:
  532. case DRM_FORMAT_RGB565:
  533. case DRM_FORMAT_BGR565:
  534. case DRM_FORMAT_UYVY:
  535. case DRM_FORMAT_YUYV:
  536. bytes_per_col = 32;
  537. break;
  538. /* 16 lines at 1.5 bytes per pixel */
  539. case DRM_FORMAT_NV12:
  540. case DRM_FORMAT_YUV420:
  541. bytes_per_col = 24;
  542. break;
  543. default:
  544. return -EINVAL;
  545. }
  546. return w * bytes_per_col;
  547. }
  548. static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
  549. struct malidp_se_config *se_config,
  550. struct malidp_se_config *old_config)
  551. {
  552. u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
  553. MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
  554. u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
  555. MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
  556. malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
  557. malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
  558. return 0;
  559. }
  560. static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
  561. struct malidp_se_config *se_config,
  562. struct videomode *vm)
  563. {
  564. unsigned long mclk;
  565. unsigned long pxlclk = vm->pixelclock;
  566. unsigned long htotal = vm->hactive + vm->hfront_porch +
  567. vm->hback_porch + vm->hsync_len;
  568. unsigned long numerator = 1, denominator = 1;
  569. long ret;
  570. if (se_config->scale_enable) {
  571. numerator = max(se_config->input_w, se_config->output_w) *
  572. se_config->input_h;
  573. numerator += se_config->output_w *
  574. (se_config->output_h -
  575. min(se_config->input_h, se_config->output_h));
  576. denominator = (htotal - 2) * se_config->output_h;
  577. }
  578. /* mclk can't be slower than pxlclk. */
  579. if (numerator < denominator)
  580. numerator = denominator = 1;
  581. mclk = (pxlclk * numerator) / denominator;
  582. ret = clk_get_rate(hwdev->mclk);
  583. if (ret < mclk) {
  584. DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
  585. mclk / 1000);
  586. return -EINVAL;
  587. }
  588. return ret;
  589. }
  590. static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
  591. dma_addr_t *addrs, s32 *pitches,
  592. int num_planes, u16 w, u16 h, u32 fmt_id,
  593. const s16 *rgb2yuv_coeffs)
  594. {
  595. u32 base = MALIDP550_SE_MEMWRITE_BASE;
  596. u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
  597. /* enable the scaling engine block */
  598. malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
  599. hwdev->mw_state = MW_ONESHOT;
  600. malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
  601. switch (num_planes) {
  602. case 2:
  603. malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
  604. malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
  605. malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
  606. /* fall through */
  607. case 1:
  608. malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
  609. malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
  610. malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
  611. break;
  612. default:
  613. WARN(1, "Invalid number of planes");
  614. }
  615. malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
  616. MALIDP550_SE_MEMWRITE_OUT_SIZE);
  617. malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
  618. MALIDP550_SE_CONTROL);
  619. if (rgb2yuv_coeffs) {
  620. int i;
  621. for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
  622. malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
  623. MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
  624. }
  625. }
  626. return 0;
  627. }
  628. static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
  629. {
  630. u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
  631. malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
  632. MALIDP550_SE_CONTROL);
  633. malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
  634. }
  635. static int malidp650_query_hw(struct malidp_hw_device *hwdev)
  636. {
  637. u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
  638. u8 ln_size = (conf >> 4) & 0x3, rsize;
  639. hwdev->min_line_size = 4;
  640. switch (ln_size) {
  641. case 0:
  642. case 2:
  643. /* reserved values */
  644. hwdev->max_line_size = 0;
  645. return -EINVAL;
  646. case 1:
  647. hwdev->max_line_size = SZ_4K;
  648. /* two banks of 128KB for rotation memory */
  649. rsize = 128;
  650. break;
  651. case 3:
  652. hwdev->max_line_size = 2560;
  653. /* two banks of 80KB for rotation memory */
  654. rsize = 80;
  655. }
  656. hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
  657. return 0;
  658. }
  659. const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
  660. [MALIDP_500] = {
  661. .map = {
  662. .coeffs_base = MALIDP500_COEFFS_BASE,
  663. .se_base = MALIDP500_SE_BASE,
  664. .dc_base = MALIDP500_DC_BASE,
  665. .out_depth_base = MALIDP500_OUTPUT_DEPTH,
  666. .features = 0, /* no CLEARIRQ register */
  667. .n_layers = ARRAY_SIZE(malidp500_layers),
  668. .layers = malidp500_layers,
  669. .de_irq_map = {
  670. .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
  671. MALIDP500_DE_IRQ_AXI_ERR |
  672. MALIDP500_DE_IRQ_VSYNC |
  673. MALIDP500_DE_IRQ_GLOBAL,
  674. .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
  675. .err_mask = MALIDP_DE_IRQ_UNDERRUN |
  676. MALIDP500_DE_IRQ_AXI_ERR |
  677. MALIDP500_DE_IRQ_SATURATION,
  678. },
  679. .se_irq_map = {
  680. .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
  681. MALIDP500_SE_IRQ_CONF_VALID |
  682. MALIDP500_SE_IRQ_GLOBAL,
  683. .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
  684. .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
  685. MALIDP500_SE_IRQ_AXI_ERROR |
  686. MALIDP500_SE_IRQ_OVERRUN,
  687. },
  688. .dc_irq_map = {
  689. .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
  690. .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
  691. },
  692. .pixel_formats = malidp500_de_formats,
  693. .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
  694. .bus_align_bytes = 8,
  695. },
  696. .query_hw = malidp500_query_hw,
  697. .enter_config_mode = malidp500_enter_config_mode,
  698. .leave_config_mode = malidp500_leave_config_mode,
  699. .in_config_mode = malidp500_in_config_mode,
  700. .set_config_valid = malidp500_set_config_valid,
  701. .modeset = malidp500_modeset,
  702. .rotmem_required = malidp500_rotmem_required,
  703. .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
  704. .se_calc_mclk = malidp500_se_calc_mclk,
  705. .enable_memwrite = malidp500_enable_memwrite,
  706. .disable_memwrite = malidp500_disable_memwrite,
  707. .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
  708. },
  709. [MALIDP_550] = {
  710. .map = {
  711. .coeffs_base = MALIDP550_COEFFS_BASE,
  712. .se_base = MALIDP550_SE_BASE,
  713. .dc_base = MALIDP550_DC_BASE,
  714. .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
  715. .features = MALIDP_REGMAP_HAS_CLEARIRQ,
  716. .n_layers = ARRAY_SIZE(malidp550_layers),
  717. .layers = malidp550_layers,
  718. .de_irq_map = {
  719. .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
  720. MALIDP550_DE_IRQ_VSYNC,
  721. .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
  722. .err_mask = MALIDP_DE_IRQ_UNDERRUN |
  723. MALIDP550_DE_IRQ_SATURATION |
  724. MALIDP550_DE_IRQ_AXI_ERR,
  725. },
  726. .se_irq_map = {
  727. .irq_mask = MALIDP550_SE_IRQ_EOW,
  728. .vsync_irq = MALIDP550_SE_IRQ_EOW,
  729. .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
  730. MALIDP550_SE_IRQ_OVR |
  731. MALIDP550_SE_IRQ_IBSY,
  732. },
  733. .dc_irq_map = {
  734. .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
  735. MALIDP550_DC_IRQ_SE,
  736. .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
  737. },
  738. .pixel_formats = malidp550_de_formats,
  739. .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
  740. .bus_align_bytes = 8,
  741. },
  742. .query_hw = malidp550_query_hw,
  743. .enter_config_mode = malidp550_enter_config_mode,
  744. .leave_config_mode = malidp550_leave_config_mode,
  745. .in_config_mode = malidp550_in_config_mode,
  746. .set_config_valid = malidp550_set_config_valid,
  747. .modeset = malidp550_modeset,
  748. .rotmem_required = malidp550_rotmem_required,
  749. .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
  750. .se_calc_mclk = malidp550_se_calc_mclk,
  751. .enable_memwrite = malidp550_enable_memwrite,
  752. .disable_memwrite = malidp550_disable_memwrite,
  753. .features = 0,
  754. },
  755. [MALIDP_650] = {
  756. .map = {
  757. .coeffs_base = MALIDP550_COEFFS_BASE,
  758. .se_base = MALIDP550_SE_BASE,
  759. .dc_base = MALIDP550_DC_BASE,
  760. .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
  761. .features = MALIDP_REGMAP_HAS_CLEARIRQ,
  762. .n_layers = ARRAY_SIZE(malidp550_layers),
  763. .layers = malidp550_layers,
  764. .de_irq_map = {
  765. .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
  766. MALIDP650_DE_IRQ_DRIFT |
  767. MALIDP550_DE_IRQ_VSYNC,
  768. .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
  769. .err_mask = MALIDP_DE_IRQ_UNDERRUN |
  770. MALIDP650_DE_IRQ_DRIFT |
  771. MALIDP550_DE_IRQ_SATURATION |
  772. MALIDP550_DE_IRQ_AXI_ERR |
  773. MALIDP650_DE_IRQ_ACEV1 |
  774. MALIDP650_DE_IRQ_ACEV2 |
  775. MALIDP650_DE_IRQ_ACEG |
  776. MALIDP650_DE_IRQ_AXIEP,
  777. },
  778. .se_irq_map = {
  779. .irq_mask = MALIDP550_SE_IRQ_EOW,
  780. .vsync_irq = MALIDP550_SE_IRQ_EOW,
  781. .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
  782. MALIDP550_SE_IRQ_OVR |
  783. MALIDP550_SE_IRQ_IBSY,
  784. },
  785. .dc_irq_map = {
  786. .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
  787. MALIDP550_DC_IRQ_SE,
  788. .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
  789. },
  790. .pixel_formats = malidp550_de_formats,
  791. .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
  792. .bus_align_bytes = 16,
  793. },
  794. .query_hw = malidp650_query_hw,
  795. .enter_config_mode = malidp550_enter_config_mode,
  796. .leave_config_mode = malidp550_leave_config_mode,
  797. .in_config_mode = malidp550_in_config_mode,
  798. .set_config_valid = malidp550_set_config_valid,
  799. .modeset = malidp550_modeset,
  800. .rotmem_required = malidp550_rotmem_required,
  801. .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
  802. .se_calc_mclk = malidp550_se_calc_mclk,
  803. .enable_memwrite = malidp550_enable_memwrite,
  804. .disable_memwrite = malidp550_disable_memwrite,
  805. .features = 0,
  806. },
  807. };
  808. u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
  809. u8 layer_id, u32 format)
  810. {
  811. unsigned int i;
  812. for (i = 0; i < map->n_pixel_formats; i++) {
  813. if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
  814. (map->pixel_formats[i].format == format))
  815. return map->pixel_formats[i].id;
  816. }
  817. return MALIDP_INVALID_FORMAT_ID;
  818. }
  819. static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
  820. {
  821. u32 base = malidp_get_block_base(hwdev, block);
  822. if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
  823. malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
  824. else
  825. malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
  826. }
  827. static irqreturn_t malidp_de_irq(int irq, void *arg)
  828. {
  829. struct drm_device *drm = arg;
  830. struct malidp_drm *malidp = drm->dev_private;
  831. struct malidp_hw_device *hwdev;
  832. struct malidp_hw *hw;
  833. const struct malidp_irq_map *de;
  834. u32 status, mask, dc_status;
  835. irqreturn_t ret = IRQ_NONE;
  836. hwdev = malidp->dev;
  837. hw = hwdev->hw;
  838. de = &hw->map.de_irq_map;
  839. /*
  840. * if we are suspended it is likely that we were invoked because
  841. * we share an interrupt line with some other driver, don't try
  842. * to read the hardware registers
  843. */
  844. if (hwdev->pm_suspended)
  845. return IRQ_NONE;
  846. /* first handle the config valid IRQ */
  847. dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
  848. if (dc_status & hw->map.dc_irq_map.vsync_irq) {
  849. malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
  850. /* do we have a page flip event? */
  851. if (malidp->event != NULL) {
  852. spin_lock(&drm->event_lock);
  853. drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
  854. malidp->event = NULL;
  855. spin_unlock(&drm->event_lock);
  856. }
  857. atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
  858. ret = IRQ_WAKE_THREAD;
  859. }
  860. status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
  861. if (!(status & de->irq_mask))
  862. return ret;
  863. mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
  864. /* keep the status of the enabled interrupts, plus the error bits */
  865. status &= (mask | de->err_mask);
  866. if ((status & de->vsync_irq) && malidp->crtc.enabled)
  867. drm_crtc_handle_vblank(&malidp->crtc);
  868. #ifdef CONFIG_DEBUG_FS
  869. if (status & de->err_mask) {
  870. malidp_error(malidp, &malidp->de_errors, status,
  871. drm_crtc_vblank_count(&malidp->crtc));
  872. }
  873. #endif
  874. malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
  875. return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
  876. }
  877. static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
  878. {
  879. struct drm_device *drm = arg;
  880. struct malidp_drm *malidp = drm->dev_private;
  881. wake_up(&malidp->wq);
  882. return IRQ_HANDLED;
  883. }
  884. void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
  885. {
  886. /* ensure interrupts are disabled */
  887. malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
  888. malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
  889. malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
  890. malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
  891. /* first enable the DC block IRQs */
  892. malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
  893. hwdev->hw->map.dc_irq_map.irq_mask);
  894. /* now enable the DE block IRQs */
  895. malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
  896. hwdev->hw->map.de_irq_map.irq_mask);
  897. }
  898. int malidp_de_irq_init(struct drm_device *drm, int irq)
  899. {
  900. struct malidp_drm *malidp = drm->dev_private;
  901. struct malidp_hw_device *hwdev = malidp->dev;
  902. int ret;
  903. /* ensure interrupts are disabled */
  904. malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
  905. malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
  906. malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
  907. malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
  908. ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
  909. malidp_de_irq_thread_handler,
  910. IRQF_SHARED, "malidp-de", drm);
  911. if (ret < 0) {
  912. DRM_ERROR("failed to install DE IRQ handler\n");
  913. return ret;
  914. }
  915. malidp_de_irq_hw_init(hwdev);
  916. return 0;
  917. }
  918. void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
  919. {
  920. malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
  921. hwdev->hw->map.de_irq_map.irq_mask);
  922. malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
  923. hwdev->hw->map.dc_irq_map.irq_mask);
  924. }
  925. static irqreturn_t malidp_se_irq(int irq, void *arg)
  926. {
  927. struct drm_device *drm = arg;
  928. struct malidp_drm *malidp = drm->dev_private;
  929. struct malidp_hw_device *hwdev = malidp->dev;
  930. struct malidp_hw *hw = hwdev->hw;
  931. const struct malidp_irq_map *se = &hw->map.se_irq_map;
  932. u32 status, mask;
  933. /*
  934. * if we are suspended it is likely that we were invoked because
  935. * we share an interrupt line with some other driver, don't try
  936. * to read the hardware registers
  937. */
  938. if (hwdev->pm_suspended)
  939. return IRQ_NONE;
  940. status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
  941. if (!(status & (se->irq_mask | se->err_mask)))
  942. return IRQ_NONE;
  943. #ifdef CONFIG_DEBUG_FS
  944. if (status & se->err_mask)
  945. malidp_error(malidp, &malidp->se_errors, status,
  946. drm_crtc_vblank_count(&malidp->crtc));
  947. #endif
  948. mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
  949. status &= mask;
  950. if (status & se->vsync_irq) {
  951. switch (hwdev->mw_state) {
  952. case MW_ONESHOT:
  953. drm_writeback_signal_completion(&malidp->mw_connector, 0);
  954. break;
  955. case MW_STOP:
  956. drm_writeback_signal_completion(&malidp->mw_connector, 0);
  957. /* disable writeback after stop */
  958. hwdev->mw_state = MW_NOT_ENABLED;
  959. break;
  960. case MW_RESTART:
  961. drm_writeback_signal_completion(&malidp->mw_connector, 0);
  962. /* fall through to a new start */
  963. case MW_START:
  964. /* writeback started, need to emulate one-shot mode */
  965. hw->disable_memwrite(hwdev);
  966. /*
  967. * only set config_valid HW bit if there is no other update
  968. * in progress or if we raced ahead of the DE IRQ handler
  969. * and config_valid flag will not be update until later
  970. */
  971. status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
  972. if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
  973. (status & hw->map.dc_irq_map.vsync_irq))
  974. hw->set_config_valid(hwdev, 1);
  975. break;
  976. }
  977. }
  978. malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
  979. return IRQ_HANDLED;
  980. }
  981. void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
  982. {
  983. /* ensure interrupts are disabled */
  984. malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
  985. malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
  986. malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
  987. hwdev->hw->map.se_irq_map.irq_mask);
  988. }
  989. static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
  990. {
  991. return IRQ_HANDLED;
  992. }
  993. int malidp_se_irq_init(struct drm_device *drm, int irq)
  994. {
  995. struct malidp_drm *malidp = drm->dev_private;
  996. struct malidp_hw_device *hwdev = malidp->dev;
  997. int ret;
  998. /* ensure interrupts are disabled */
  999. malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
  1000. malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
  1001. ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
  1002. malidp_se_irq_thread_handler,
  1003. IRQF_SHARED, "malidp-se", drm);
  1004. if (ret < 0) {
  1005. DRM_ERROR("failed to install SE IRQ handler\n");
  1006. return ret;
  1007. }
  1008. hwdev->mw_state = MW_NOT_ENABLED;
  1009. malidp_se_irq_hw_init(hwdev);
  1010. return 0;
  1011. }
  1012. void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
  1013. {
  1014. malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
  1015. hwdev->hw->map.se_irq_map.irq_mask);
  1016. }