blob: aa8186db830080b205f6fbeff4ebce4ee1b2c238 [file] [log] [blame]
Googler9398cc32022-12-02 17:21:52 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
Googler4f18c0c2022-09-20 17:23:36 +08002/*
Googler9398cc32022-12-02 17:21:52 +08003 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
Googler4f18c0c2022-09-20 17:23:36 +08004 */
5
Googler9726be62022-12-14 05:53:31 +00006#include <linux/module.h>
7#include <linux/init.h>
8#include <linux/fs.h>
9#include <linux/uaccess.h>
10
Googler4f18c0c2022-09-20 17:23:36 +080011#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
12#include <linux/amlogic/media/canvas/canvas.h>
13#include <linux/amlogic/media/canvas/canvas_mgr.h>
14#endif
15#include "meson_vpu_pipeline.h"
Googler9726be62022-12-14 05:53:31 +000016#include "meson_crtc.h"
Googler4f18c0c2022-09-20 17:23:36 +080017#include "meson_vpu_reg.h"
18#include "meson_vpu_util.h"
19
Googler9398cc32022-12-02 17:21:52 +080020static int osd_hold_line = 8;
21module_param(osd_hold_line, int, 0664);
22MODULE_PARM_DESC(osd_hold_line, "osd_hold_line");
23
Googler4f18c0c2022-09-20 17:23:36 +080024static struct osd_mif_reg_s osd_mif_reg[HW_OSD_MIF_NUM] = {
25 {
26 VIU_OSD1_CTRL_STAT,
27 VIU_OSD1_CTRL_STAT2,
28 VIU_OSD1_COLOR_ADDR,
29 VIU_OSD1_COLOR,
30 VIU_OSD1_TCOLOR_AG0,
31 VIU_OSD1_TCOLOR_AG1,
32 VIU_OSD1_TCOLOR_AG2,
33 VIU_OSD1_TCOLOR_AG3,
34 VIU_OSD1_BLK0_CFG_W0,
35 VIU_OSD1_BLK0_CFG_W1,
36 VIU_OSD1_BLK0_CFG_W2,
37 VIU_OSD1_BLK0_CFG_W3,
38 VIU_OSD1_BLK0_CFG_W4,
39 VIU_OSD1_BLK1_CFG_W4,
40 VIU_OSD1_BLK2_CFG_W4,
41 VIU_OSD1_FIFO_CTRL_STAT,
42 VIU_OSD1_TEST_RDDATA,
43 VIU_OSD1_PROT_CTRL,
44 VIU_OSD1_MALI_UNPACK_CTRL,
45 VIU_OSD1_DIMM_CTRL,
46 },
47 {
48 VIU_OSD2_CTRL_STAT,
49 VIU_OSD2_CTRL_STAT2,
50 VIU_OSD2_COLOR_ADDR,
51 VIU_OSD2_COLOR,
52 VIU_OSD2_TCOLOR_AG0,
53 VIU_OSD2_TCOLOR_AG1,
54 VIU_OSD2_TCOLOR_AG2,
55 VIU_OSD2_TCOLOR_AG3,
56 VIU_OSD2_BLK0_CFG_W0,
57 VIU_OSD2_BLK0_CFG_W1,
58 VIU_OSD2_BLK0_CFG_W2,
59 VIU_OSD2_BLK0_CFG_W3,
60 VIU_OSD2_BLK0_CFG_W4,
61 VIU_OSD2_BLK1_CFG_W4,
62 VIU_OSD2_BLK2_CFG_W4,
63 VIU_OSD2_FIFO_CTRL_STAT,
64 VIU_OSD2_TEST_RDDATA,
65 VIU_OSD2_PROT_CTRL,
66 VIU_OSD2_MALI_UNPACK_CTRL,
67 VIU_OSD2_DIMM_CTRL,
68 },
69 {
70 VIU_OSD3_CTRL_STAT,
71 VIU_OSD3_CTRL_STAT2,
72 VIU_OSD3_COLOR_ADDR,
73 VIU_OSD3_COLOR,
74 VIU_OSD3_TCOLOR_AG0,
75 VIU_OSD3_TCOLOR_AG1,
76 VIU_OSD3_TCOLOR_AG2,
77 VIU_OSD3_TCOLOR_AG3,
78 VIU_OSD3_BLK0_CFG_W0,
79 VIU_OSD3_BLK0_CFG_W1,
80 VIU_OSD3_BLK0_CFG_W2,
81 VIU_OSD3_BLK0_CFG_W3,
82 VIU_OSD3_BLK0_CFG_W4,
83 VIU_OSD3_BLK1_CFG_W4,
84 VIU_OSD3_BLK2_CFG_W4,
85 VIU_OSD3_FIFO_CTRL_STAT,
86 VIU_OSD3_TEST_RDDATA,
87 VIU_OSD3_PROT_CTRL,
88 VIU_OSD3_MALI_UNPACK_CTRL,
89 VIU_OSD3_DIMM_CTRL,
90 }
91};
92
Googler9726be62022-12-14 05:53:31 +000093static unsigned int osd_canvas[3][2];
Googler4f18c0c2022-09-20 17:23:36 +080094static u32 osd_canvas_index[3] = {0, 0, 0};
95
96/*
97 * Internal function to query information for a given format. See
98 * meson_drm_format_info() for the public API.
99 */
100const struct meson_drm_format_info *__meson_drm_format_info(u32 format)
101{
102 static const struct meson_drm_format_info formats[] = {
103 { .format = DRM_FORMAT_XRGB8888,
Googler9726be62022-12-14 05:53:31 +0000104 .hw_blkmode = BLOCK_MODE_32BIT,
105 .hw_colormat = COLOR_MATRIX_ARGB8888,
106 .alpha_replace = 1 },
Googler4f18c0c2022-09-20 17:23:36 +0800107 { .format = DRM_FORMAT_XBGR8888,
Googler9726be62022-12-14 05:53:31 +0000108 .hw_blkmode = BLOCK_MODE_32BIT,
109 .hw_colormat = COLOR_MATRIX_ABGR8888,
110 .alpha_replace = 1 },
Googler4f18c0c2022-09-20 17:23:36 +0800111 { .format = DRM_FORMAT_RGBX8888,
Googler9726be62022-12-14 05:53:31 +0000112 .hw_blkmode = BLOCK_MODE_32BIT,
113 .hw_colormat = COLOR_MATRIX_RGBA8888,
114 .alpha_replace = 1 },
Googler4f18c0c2022-09-20 17:23:36 +0800115 { .format = DRM_FORMAT_BGRX8888,
Googler9726be62022-12-14 05:53:31 +0000116 .hw_blkmode = BLOCK_MODE_32BIT,
117 .hw_colormat = COLOR_MATRIX_BGRA8888,
118 .alpha_replace = 1 },
Googler4f18c0c2022-09-20 17:23:36 +0800119 { .format = DRM_FORMAT_ARGB8888,
Googler9726be62022-12-14 05:53:31 +0000120 .hw_blkmode = BLOCK_MODE_32BIT,
121 .hw_colormat = COLOR_MATRIX_ARGB8888,
122 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800123 { .format = DRM_FORMAT_ABGR8888,
Googler9726be62022-12-14 05:53:31 +0000124 .hw_blkmode = BLOCK_MODE_32BIT,
125 .hw_colormat = COLOR_MATRIX_ABGR8888,
126 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800127 { .format = DRM_FORMAT_RGBA8888,
Googler9726be62022-12-14 05:53:31 +0000128 .hw_blkmode = BLOCK_MODE_32BIT,
129 .hw_colormat = COLOR_MATRIX_RGBA8888,
130 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800131 { .format = DRM_FORMAT_BGRA8888,
Googler9726be62022-12-14 05:53:31 +0000132 .hw_blkmode = BLOCK_MODE_32BIT,
133 .hw_colormat = COLOR_MATRIX_BGRA8888,
134 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800135 { .format = DRM_FORMAT_RGB888,
Googler9726be62022-12-14 05:53:31 +0000136 .hw_blkmode = BLOCK_MODE_24BIT,
137 .hw_colormat = COLOR_MATRIX_RGB888,
138 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800139 { .format = DRM_FORMAT_RGB565,
Googler9726be62022-12-14 05:53:31 +0000140 .hw_blkmode = BLOCK_MODE_16BIT,
141 .hw_colormat = COLOR_MATRIX_565,
142 .alpha_replace = 0 },
143 };
144
145 unsigned int i;
146
147 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
148 if (formats[i].format == format)
149 return &formats[i];
150 }
151
152 return NULL;
153}
154
155const struct meson_drm_format_info *__meson_drm_afbc_format_info(u32 format)
156{
157 static const struct meson_drm_format_info formats[] = {
158 { .format = DRM_FORMAT_XRGB8888,
159 .hw_blkmode = BLOCK_MODE_RGBA8888,
160 .alpha_replace = 1 },
161 { .format = DRM_FORMAT_XBGR8888,
162 .hw_blkmode = BLOCK_MODE_RGBA8888,
163 .alpha_replace = 1 },
164 { .format = DRM_FORMAT_RGBX8888,
165 .hw_blkmode = BLOCK_MODE_RGBA8888,
166 .alpha_replace = 1 },
167 { .format = DRM_FORMAT_BGRX8888,
168 .hw_blkmode = BLOCK_MODE_RGBA8888,
169 .alpha_replace = 1 },
170 { .format = DRM_FORMAT_ARGB8888,
171 .hw_blkmode = BLOCK_MODE_RGBA8888,
172 .alpha_replace = 0 },
173 { .format = DRM_FORMAT_ABGR8888,
174 .hw_blkmode = BLOCK_MODE_RGBA8888,
175 .alpha_replace = 0 },
176 { .format = DRM_FORMAT_RGBA8888,
177 .hw_blkmode = BLOCK_MODE_RGBA8888,
178 .alpha_replace = 0 },
179 { .format = DRM_FORMAT_BGRA8888,
180 .hw_blkmode = BLOCK_MODE_RGBA8888,
181 .alpha_replace = 0 },
182 { .format = DRM_FORMAT_RGB888,
183 .hw_blkmode = BLOCK_MODE_RGB888,
184 .alpha_replace = 0 },
185 { .format = DRM_FORMAT_RGB565,
186 .hw_blkmode = BLOCK_MODE_RGB565,
187 .alpha_replace = 0 },
188 { .format = DRM_FORMAT_RGBA1010102,
189 .hw_blkmode = BLOCK_MODE_RGBA1010102,
190 .alpha_replace = 0 },
Googler4f18c0c2022-09-20 17:23:36 +0800191 };
192
193 unsigned int i;
194
195 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
196 if (formats[i].format == format)
197 return &formats[i];
198 }
199
200 return NULL;
201}
202
203/**
204 * meson_drm_format_info - query information for a given format
205 * @format: pixel format (DRM_FORMAT_*)
206 *
207 * The caller should only pass a supported pixel format to this function.
208 * Unsupported pixel formats will generate a warning in the kernel log.
209 *
210 * Returns:
211 * The instance of struct meson_drm_format_info that describes the
212 * pixel format, or NULL if the format is unsupported.
213 */
Googler9726be62022-12-14 05:53:31 +0000214const struct meson_drm_format_info *meson_drm_format_info(u32 format,
215 bool afbc_en)
Googler4f18c0c2022-09-20 17:23:36 +0800216{
217 const struct meson_drm_format_info *info;
218
Googler9726be62022-12-14 05:53:31 +0000219 if (afbc_en)
220 info = __meson_drm_afbc_format_info(format);
221 else
222 info = __meson_drm_format_info(format);
Googler4f18c0c2022-09-20 17:23:36 +0800223 WARN_ON(!info);
224 return info;
225}
Googler38bda472022-08-19 10:07:08 -0700226
Googler4f18c0c2022-09-20 17:23:36 +0800227/**
228 * meson_drm_format_hw_blkmode - get the hw_blkmode for format
229 * @format: pixel format (DRM_FORMAT_*)
230 *
231 * Returns:
232 * The hw_blkmode match the specified pixel format.
233 */
Googler9726be62022-12-14 05:53:31 +0000234static u8 meson_drm_format_hw_blkmode(u32 format, bool afbc_en)
Googler4f18c0c2022-09-20 17:23:36 +0800235{
236 const struct meson_drm_format_info *info;
237
Googler9726be62022-12-14 05:53:31 +0000238 info = meson_drm_format_info(format, afbc_en);
Googler4f18c0c2022-09-20 17:23:36 +0800239 return info ? info->hw_blkmode : 0;
240}
Googler38bda472022-08-19 10:07:08 -0700241
Googler4f18c0c2022-09-20 17:23:36 +0800242/**
243 * meson_drm_format_hw_colormat - get the hw_colormat for format
244 * @format: pixel format (DRM_FORMAT_*)
245 *
246 * Returns:
247 * The hw_colormat match the specified pixel format.
248 */
Googler9726be62022-12-14 05:53:31 +0000249static u8 meson_drm_format_hw_colormat(u32 format, bool afbc_en)
Googler4f18c0c2022-09-20 17:23:36 +0800250{
251 const struct meson_drm_format_info *info;
252
Googler9726be62022-12-14 05:53:31 +0000253 info = meson_drm_format_info(format, afbc_en);
Googler4f18c0c2022-09-20 17:23:36 +0800254 return info ? info->hw_colormat : 0;
255}
Googler38bda472022-08-19 10:07:08 -0700256
Googler4f18c0c2022-09-20 17:23:36 +0800257/**
258 * meson_drm_format_alpha_replace - get the alpha replace for format
259 * @format: pixel format (DRM_FORMAT_*)
260 *
261 * Returns:
262 * The alpha_replace match the specified pixel format.
263 */
Googler9726be62022-12-14 05:53:31 +0000264static u8 meson_drm_format_alpha_replace(u32 format, bool afbc_en)
Googler4f18c0c2022-09-20 17:23:36 +0800265{
266 const struct meson_drm_format_info *info;
267
Googler9726be62022-12-14 05:53:31 +0000268 info = meson_drm_format_info(format, afbc_en);
Googler4f18c0c2022-09-20 17:23:36 +0800269 return info ? info->alpha_replace : 0;
270}
Googler38bda472022-08-19 10:07:08 -0700271
Googler9398cc32022-12-02 17:21:52 +0800272/*osd hold line config*/
273void ods_hold_line_config(struct osd_mif_reg_s *reg, int hold_line)
274{
275 u32 data = 0, value = 0;
276
277 data = meson_drm_read_reg(reg->viu_osd_fifo_ctrl_stat);
278 value = (data >> 5) & 0x1f;
279 if (value != hold_line)
280 meson_vpu_write_reg_bits(reg->viu_osd_fifo_ctrl_stat,
281 hold_line & 0x1f, 5, 5);
282}
283
Googler4f18c0c2022-09-20 17:23:36 +0800284/*osd input size config*/
285void osd_input_size_config(struct osd_mif_reg_s *reg, struct osd_scope_s scope)
286{
Googler9726be62022-12-14 05:53:31 +0000287 meson_vpu_write_reg(reg->viu_osd_blk0_cfg_w1,
288 (scope.h_end << 16) | /*x_end pixels[13bits]*/
Googler4f18c0c2022-09-20 17:23:36 +0800289 scope.h_start/*x_start pixels[13bits]*/);
Googler9726be62022-12-14 05:53:31 +0000290 meson_vpu_write_reg(reg->viu_osd_blk0_cfg_w2,
291 (scope.v_end << 16) | /*y_end pixels[13bits]*/
Googler4f18c0c2022-09-20 17:23:36 +0800292 scope.v_start/*y_start pixels[13bits]*/);
293}
Googler38bda472022-08-19 10:07:08 -0700294
Googler4f18c0c2022-09-20 17:23:36 +0800295/*osd canvas config*/
296void osd_canvas_config(struct osd_mif_reg_s *reg, u32 canvas_index)
297{
Googler9726be62022-12-14 05:53:31 +0000298 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0,
299 canvas_index, 16, 8);
300}
301
302/*osd mali afbc src en
303 * 1: read data from mali afbcd;0: read data from DDR directly
304 */
305void osd_mali_src_en(struct osd_mif_reg_s *reg, u8 osd_index, bool flag)
306{
307 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0, flag, 30, 1);
308 meson_vpu_write_reg_bits(OSD_PATH_MISC_CTRL, flag, (osd_index + 4), 1);
309}
310
311/*osd endian mode
312 * 1: little endian;0: big endian[for mali afbc input]
313 */
314void osd_endian_mode(struct osd_mif_reg_s *reg, bool flag)
315{
316 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0, flag, 15, 1);
Googler4f18c0c2022-09-20 17:23:36 +0800317}
318
319/*osd mif enable*/
320void osd_block_enable(struct osd_mif_reg_s *reg, bool flag)
321{
Googler9726be62022-12-14 05:53:31 +0000322 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat, flag, 0, 1);
323}
324
325/*osd mem mode
326 * 0: canvas_addr;1:linear_addr[for mali-afbc-mode]
327 */
328void osd_mem_mode(struct osd_mif_reg_s *reg, bool mode)
329{
330 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat, mode, 2, 1);
Googler4f18c0c2022-09-20 17:23:36 +0800331}
332
333/*osd alpha_div en
334 *if input is premult,alpha_div=1,else alpha_div=0
335 */
Googler9398cc32022-12-02 17:21:52 +0800336void osd_global_alpha_set(struct osd_mif_reg_s *reg, u16 val)
Googler4f18c0c2022-09-20 17:23:36 +0800337{
Googler9398cc32022-12-02 17:21:52 +0800338 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat, val, 12, 9);
339}
340
341/*osd alpha_div en
342 *if input is premult,alpha_div=1,else alpha_div=0
343 */
344void osd_premult_enable(struct osd_mif_reg_s *reg, int flag)
345{
346 /*afbc*/
Googler9726be62022-12-14 05:53:31 +0000347 meson_vpu_write_reg_bits(reg->viu_osd_mali_unpack_ctrl, flag, 28, 1);
Googler9398cc32022-12-02 17:21:52 +0800348 /*mif*/
349 //meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat, flag, 1, 1);
Googler9726be62022-12-14 05:53:31 +0000350}
351
352/*osd x reverse en
353 *reverse read in X direction
354 */
355void osd_reverse_x_enable(struct osd_mif_reg_s *reg, bool flag)
356{
357 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0, flag, 28, 1);
358}
359
360/*osd y reverse en
361 *reverse read in Y direction
362 */
363void osd_reverse_y_enable(struct osd_mif_reg_s *reg, bool flag)
364{
365 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0, flag, 29, 1);
366}
367
368/*osd mali unpack en
369 * 1: osd will unpack mali_afbc_src;0:osd will unpack normal src
370 */
371void osd_mali_unpack_enable(struct osd_mif_reg_s *reg, bool flag)
372{
373 meson_vpu_write_reg_bits(reg->viu_osd_mali_unpack_ctrl, flag, 31, 1);
374}
375
Googler9398cc32022-12-02 17:21:52 +0800376void osd_ctrl_init(struct osd_mif_reg_s *reg)
Googler9726be62022-12-14 05:53:31 +0000377{
Googler9398cc32022-12-02 17:21:52 +0800378 /*Need config follow crtc index.*/
379 u8 holdline = VIU1_DEFAULT_HOLD_LINE;
Googler38bda472022-08-19 10:07:08 -0700380
Googler9726be62022-12-14 05:53:31 +0000381 meson_vpu_write_reg(reg->viu_osd_fifo_ctrl_stat,
382 (1 << 31) | /*BURSET_LEN_SEL[2]*/
Googler9398cc32022-12-02 17:21:52 +0800383 (0 << 30) | /*no swap*/
384 (0 << 29) | /*div swap*/
385 (2 << 24) | /*Fifo_lim 5bits*/
386 (2 << 22) | /*Fifo_ctrl 2bits*/
387 (0x20 << 12) | /*FIFO_DEPATH_VAL 7bits*/
388 (1 << 10) | /*BURSET_LEN_SEL[1:0]*/
389 (holdline << 5) | /*hold fifo lines 5bits*/
390 (0 << 4) | /*CLEAR_ERR*/
391 (0 << 3) | /*fifo_sync_rst*/
392 (0 << 1) | /*ENDIAN:no conversion*/
393 (1 << 0)/*urgent enable*/);
394 meson_vpu_write_reg(reg->viu_osd_ctrl_stat,
395 (0 << 31) | /*osd_cfg_sync_en*/
396 (0 << 30) | /*Enable free_clk*/
397 (0x100 << 12) | /*global alpha*/
398 (0 << 11) | /*TEST_RD_EN*/
399 (0 << 2) | /*osd_mem_mode 0:canvas_addr*/
400 (0 << 1) | /*premult_en*/
401 (0 << 0)/*OSD_BLK_ENABLE*/);
Googler4f18c0c2022-09-20 17:23:36 +0800402}
403
Googler9726be62022-12-14 05:53:31 +0000404static void osd_color_config(struct osd_mif_reg_s *reg,
Googler9398cc32022-12-02 17:21:52 +0800405 u32 pixel_format, u32 pixel_blend, bool afbc_en)
Googler4f18c0c2022-09-20 17:23:36 +0800406{
407 u8 blk_mode, colormat, alpha_replace;
408
Googler9726be62022-12-14 05:53:31 +0000409 blk_mode = meson_drm_format_hw_blkmode(pixel_format, afbc_en);
410 colormat = meson_drm_format_hw_colormat(pixel_format, afbc_en);
Googler9398cc32022-12-02 17:21:52 +0800411 alpha_replace = (pixel_blend == DRM_MODE_BLEND_PIXEL_NONE) ||
412 meson_drm_format_alpha_replace(pixel_format, afbc_en);
Googler9726be62022-12-14 05:53:31 +0000413 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0,
414 blk_mode, 8, 4);
415 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0,
416 colormat, 2, 4);
Googler9398cc32022-12-02 17:21:52 +0800417
418 if (alpha_replace)
419 /*replace alpha : bit 14 enable, 6~13 alpha val.*/
420 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat2, 0x1ff, 6, 9);
421 else
422 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat2, 0x0, 6, 9);
Googler9726be62022-12-14 05:53:31 +0000423}
424
425static void osd_afbc_config(struct osd_mif_reg_s *reg,
426 u8 osd_index, bool afbc_en)
427{
Googler9398cc32022-12-02 17:21:52 +0800428 if (!afbc_en)
429 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat2, 0, 1, 1);
430 else
431 meson_vpu_write_reg_bits(reg->viu_osd_ctrl_stat2, 1, 1, 1);
432
Googler9726be62022-12-14 05:53:31 +0000433 osd_mali_unpack_enable(reg, afbc_en);
434 osd_mali_src_en(reg, osd_index, afbc_en);
435 osd_endian_mode(reg, !afbc_en);
436 osd_mem_mode(reg, afbc_en);
437}
438
Googler9398cc32022-12-02 17:21:52 +0800439static void osd_scan_mode_config(struct osd_mif_reg_s *reg, int scan_mode)
Googler9726be62022-12-14 05:53:31 +0000440{
Googler9398cc32022-12-02 17:21:52 +0800441 if (scan_mode)
442 meson_vpu_write_reg_bits(reg->viu_osd_blk0_cfg_w0, 0, 1, 1);
Googler9726be62022-12-14 05:53:31 +0000443}
444
Googler9398cc32022-12-02 17:21:52 +0800445static void meson_drm_osd_canvas_alloc(void)
Googler9726be62022-12-14 05:53:31 +0000446{
447 if (canvas_pool_alloc_canvas_table("osd_drm",
448 &osd_canvas[0][0],
449 sizeof(osd_canvas) /
450 sizeof(osd_canvas[0][0]),
451 CANVAS_MAP_TYPE_1)) {
452 DRM_INFO("allocate drm osd canvas error.\n");
453 }
454}
455
Googler9398cc32022-12-02 17:21:52 +0800456static void meson_drm_osd_canvas_free(void)
Googler9726be62022-12-14 05:53:31 +0000457{
458 canvas_pool_free_canvas_table(&osd_canvas[0][0],
459 sizeof(osd_canvas) /
460 sizeof(osd_canvas[0][0]));
Googler38bda472022-08-19 10:07:08 -0700461}
462
Googler4f18c0c2022-09-20 17:23:36 +0800463static int osd_check_state(struct meson_vpu_block *vblk,
Googler38bda472022-08-19 10:07:08 -0700464 struct meson_vpu_block_state *state,
Googler4f18c0c2022-09-20 17:23:36 +0800465 struct meson_vpu_pipeline_state *mvps)
466{
467 struct meson_vpu_osd_layer_info *plane_info;
468 struct meson_vpu_osd *osd = to_osd_block(vblk);
469 struct meson_vpu_osd_state *mvos = to_osd_state(state);
470
471 if (state->checked)
472 return 0;
473
474 state->checked = true;
475
476 if (!mvos || mvos->plane_index >= MESON_MAX_OSDS) {
477 DRM_INFO("mvos is NULL!\n");
478 return -1;
479 }
Googler9726be62022-12-14 05:53:31 +0000480 DRM_DEBUG("%s - %d check_state called.\n", osd->base.name, vblk->index);
Googler4f18c0c2022-09-20 17:23:36 +0800481 plane_info = &mvps->plane_info[vblk->index];
482 mvos->src_x = plane_info->src_x;
483 mvos->src_y = plane_info->src_y;
484 mvos->src_w = plane_info->src_w;
485 mvos->src_h = plane_info->src_h;
486 mvos->byte_stride = plane_info->byte_stride;
487 mvos->phy_addr = plane_info->phy_addr;
488 mvos->pixel_format = plane_info->pixel_format;
Googler9726be62022-12-14 05:53:31 +0000489 mvos->fb_size = plane_info->fb_size;
Googler9398cc32022-12-02 17:21:52 +0800490 mvos->pixel_blend = plane_info->pixel_blend;
Googler9726be62022-12-14 05:53:31 +0000491 mvos->rotation = plane_info->rotation;
492 mvos->afbc_en = plane_info->afbc_en;
493 mvos->blend_bypass = plane_info->blend_bypass;
494 mvos->plane_index = plane_info->plane_index;
Googler9398cc32022-12-02 17:21:52 +0800495 mvos->global_alpha = plane_info->global_alpha;
Googler4f18c0c2022-09-20 17:23:36 +0800496 return 0;
497}
498
499static void osd_set_state(struct meson_vpu_block *vblk,
Googler38bda472022-08-19 10:07:08 -0700500 struct meson_vpu_block_state *state)
Googler4f18c0c2022-09-20 17:23:36 +0800501{
Googler9726be62022-12-14 05:53:31 +0000502 struct drm_crtc *crtc;
503 struct am_meson_crtc *amc;
504 struct meson_vpu_osd *osd;
505 struct meson_vpu_osd_state *mvos;
506 u32 pixel_format, canvas_index, src_h, byte_stride;
Googler4f18c0c2022-09-20 17:23:36 +0800507 struct osd_scope_s scope_src = {0, 1919, 0, 1079};
Googler9726be62022-12-14 05:53:31 +0000508 struct osd_mif_reg_s *reg;
Googler9398cc32022-12-02 17:21:52 +0800509 bool alpha_div_en = 0, reverse_x, reverse_y, afbc_en;
Googler9726be62022-12-14 05:53:31 +0000510 u64 phy_addr;
Googler9398cc32022-12-02 17:21:52 +0800511 u16 global_alpha = 256; /*range 0~256*/
512
Googler38bda472022-08-19 10:07:08 -0700513
Googler9726be62022-12-14 05:53:31 +0000514 if (!vblk || !state) {
Googler38bda472022-08-19 10:07:08 -0700515 DRM_DEBUG("set_state break for NULL.\n");
516 return;
517 }
Googler9726be62022-12-14 05:53:31 +0000518
519 osd = to_osd_block(vblk);
520 mvos = to_osd_state(state);
521
522 reg = osd->reg;
523 if (!reg) {
524 DRM_DEBUG("set_state break for NULL OSD mixer reg.\n");
525 return;
526 }
527
528 crtc = vblk->pipeline->crtc;
529 if (!crtc) {
530 DRM_DEBUG("set_state break for NULL crtc.\n");
531 return;
532 }
533
534 amc = to_am_meson_crtc(crtc);
535
Googler9398cc32022-12-02 17:21:52 +0800536 DRM_DEBUG("%s - %d %s called.\n", osd->base.name, vblk->index, __func__);
Googler9726be62022-12-14 05:53:31 +0000537
Googler9726be62022-12-14 05:53:31 +0000538 afbc_en = mvos->afbc_en ? 1 : 0;
Googler9398cc32022-12-02 17:21:52 +0800539 if (mvos->pixel_blend == DRM_MODE_BLEND_PREMULTI)
540 alpha_div_en = 1;
541
542 /*drm alaph 16bit, amlogic alpha 8bit*/
543 global_alpha = mvos->global_alpha >> 8;
544 if (global_alpha == 0xff)
545 global_alpha = 0x100;
546
547 src_h = mvos->src_h + mvos->src_y;
Googler4f18c0c2022-09-20 17:23:36 +0800548 byte_stride = mvos->byte_stride;
549 phy_addr = mvos->phy_addr;
550 scope_src.h_start = mvos->src_x;
551 scope_src.h_end = mvos->src_x + mvos->src_w - 1;
552 scope_src.v_start = mvos->src_y;
553 scope_src.v_end = mvos->src_y + mvos->src_h - 1;
554 pixel_format = mvos->pixel_format;
555 canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]];
Googler9398cc32022-12-02 17:21:52 +0800556
557 reverse_x = (mvos->rotation & DRM_MODE_REFLECT_X) ? 1 : 0;
558 reverse_y = (mvos->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0;
Googler9726be62022-12-14 05:53:31 +0000559 osd_reverse_x_enable(reg, reverse_x);
560 osd_reverse_y_enable(reg, reverse_y);
Googler4f18c0c2022-09-20 17:23:36 +0800561 canvas_config(canvas_index, phy_addr, byte_stride, src_h,
Googler38bda472022-08-19 10:07:08 -0700562 CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
Googler4f18c0c2022-09-20 17:23:36 +0800563 osd_canvas_index[vblk->index] ^= 1;
564 osd_canvas_config(reg, canvas_index);
565 osd_input_size_config(reg, scope_src);
Googler9398cc32022-12-02 17:21:52 +0800566 osd_color_config(reg, pixel_format, mvos->pixel_blend, afbc_en);
Googler9726be62022-12-14 05:53:31 +0000567 osd_afbc_config(reg, vblk->index, afbc_en);
Googler9398cc32022-12-02 17:21:52 +0800568 osd_premult_enable(reg, alpha_div_en);
569 osd_global_alpha_set(reg, global_alpha);
570 osd_scan_mode_config(reg, vblk->pipeline->mode.flags &
571 DRM_MODE_FLAG_INTERLACE);
572 ods_hold_line_config(reg, osd_hold_line);
573
Googler4f18c0c2022-09-20 17:23:36 +0800574 DRM_DEBUG("plane_index=%d,HW-OSD=%d\n",
Googler38bda472022-08-19 10:07:08 -0700575 mvos->plane_index, vblk->index);
Googler9726be62022-12-14 05:53:31 +0000576 DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%pa\n",
577 osd_canvas_index[vblk->index], canvas_index, &phy_addr);
Googler4f18c0c2022-09-20 17:23:36 +0800578 DRM_DEBUG("scope h/v start/end:[%d/%d/%d/%d]\n",
Googler38bda472022-08-19 10:07:08 -0700579 scope_src.h_start, scope_src.h_end,
Googler4f18c0c2022-09-20 17:23:36 +0800580 scope_src.v_start, scope_src.v_end);
581 DRM_DEBUG("%s set_state done.\n", osd->base.name);
Googler4f18c0c2022-09-20 17:23:36 +0800582}
583
584static void osd_hw_enable(struct meson_vpu_block *vblk)
585{
586 struct meson_vpu_osd *osd = to_osd_block(vblk);
587 struct osd_mif_reg_s *reg = osd->reg;
588
589 if (!vblk) {
590 DRM_DEBUG("enable break for NULL.\n");
591 return;
592 }
593 osd_block_enable(reg, 1);
594 DRM_DEBUG("%s enable done.\n", osd->base.name);
595}
596
597static void osd_hw_disable(struct meson_vpu_block *vblk)
598{
Googler9398cc32022-12-02 17:21:52 +0800599 struct meson_vpu_osd *osd;
600 struct osd_mif_reg_s *reg;
Googler9726be62022-12-14 05:53:31 +0000601 u8 version;
Googler4f18c0c2022-09-20 17:23:36 +0800602
603 if (!vblk) {
604 DRM_DEBUG("disable break for NULL.\n");
605 return;
606 }
Googler9726be62022-12-14 05:53:31 +0000607
Googler9398cc32022-12-02 17:21:52 +0800608 osd = to_osd_block(vblk);
609 reg = osd->reg;
Googler9726be62022-12-14 05:53:31 +0000610 version = vblk->pipeline->osd_version;
611
612 /*G12B should always enable,avoid afbc decoder error*/
Googler9398cc32022-12-02 17:21:52 +0800613 if (version != OSD_V2 && version != OSD_V3)
Googler9726be62022-12-14 05:53:31 +0000614 osd_block_enable(reg, 0);
Googler4f18c0c2022-09-20 17:23:36 +0800615 DRM_DEBUG("%s disable done.\n", osd->base.name);
616}
617
Googler9726be62022-12-14 05:53:31 +0000618static void osd_dump_register(struct meson_vpu_block *vblk,
619 struct seq_file *seq)
620{
621 int osd_index;
622 u32 value;
623 char buff[8];
624 struct meson_vpu_osd *osd;
625 struct osd_mif_reg_s *reg;
626
627 osd_index = vblk->index;
628 osd = to_osd_block(vblk);
629 reg = osd->reg;
630
631 snprintf(buff, 8, "OSD%d", osd_index + 1);
632
633 value = meson_drm_read_reg(reg->viu_osd_fifo_ctrl_stat);
634 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "FIFO_CTRL_STAT:", value);
635
636 value = meson_drm_read_reg(reg->viu_osd_ctrl_stat);
637 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "CTRL_STAT:", value);
638
639 value = meson_drm_read_reg(reg->viu_osd_ctrl_stat2);
640 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "CTRL_STAT2:", value);
641
642 value = meson_drm_read_reg(reg->viu_osd_blk0_cfg_w0);
643 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK0_CFG_W0:", value);
644
645 value = meson_drm_read_reg(reg->viu_osd_blk0_cfg_w1);
646 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK0_CFG_W1:", value);
647
648 value = meson_drm_read_reg(reg->viu_osd_blk0_cfg_w2);
649 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK0_CFG_W2:", value);
650
651 value = meson_drm_read_reg(reg->viu_osd_blk0_cfg_w3);
652 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK0_CFG_W3:", value);
653
654 value = meson_drm_read_reg(reg->viu_osd_blk0_cfg_w4);
655 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK0_CFG_W4:", value);
656
657 value = meson_drm_read_reg(reg->viu_osd_blk1_cfg_w4);
658 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK1_CFG_W4:", value);
659
660 value = meson_drm_read_reg(reg->viu_osd_blk2_cfg_w4);
661 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "BLK2_CFG_W4:", value);
662
663 value = meson_drm_read_reg(reg->viu_osd_prot_ctrl);
664 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "PROT_CTRL:", value);
665
666 value = meson_drm_read_reg(reg->viu_osd_mali_unpack_ctrl);
667 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "MALI_UNPACK_CTRL:", value);
668
669 value = meson_drm_read_reg(reg->viu_osd_dimm_ctrl);
670 seq_printf(seq, "%s_%-35s\t0x%08X\n", buff, "DIMM_CTRL:", value);
671}
672
Googler4f18c0c2022-09-20 17:23:36 +0800673static void osd_hw_init(struct meson_vpu_block *vblk)
674{
675 struct meson_vpu_osd *osd = to_osd_block(vblk);
676
677 if (!vblk || !osd) {
678 DRM_DEBUG("hw_init break for NULL.\n");
679 return;
680 }
Googler9398cc32022-12-02 17:21:52 +0800681
682 meson_drm_osd_canvas_alloc();
683
Googler4f18c0c2022-09-20 17:23:36 +0800684 osd->reg = &osd_mif_reg[vblk->index];
Googler9398cc32022-12-02 17:21:52 +0800685 osd_ctrl_init(osd->reg);
686
Googler4f18c0c2022-09-20 17:23:36 +0800687 DRM_DEBUG("%s hw_init done.\n", osd->base.name);
688}
689
Googler9398cc32022-12-02 17:21:52 +0800690static void osd_hw_fini(struct meson_vpu_block *vblk)
691{
692 meson_drm_osd_canvas_free();
693}
694
Googler4f18c0c2022-09-20 17:23:36 +0800695struct meson_vpu_block_ops osd_ops = {
696 .check_state = osd_check_state,
697 .update_state = osd_set_state,
698 .enable = osd_hw_enable,
699 .disable = osd_hw_disable,
Googler9726be62022-12-14 05:53:31 +0000700 .dump_register = osd_dump_register,
Googler4f18c0c2022-09-20 17:23:36 +0800701 .init = osd_hw_init,
Googler9398cc32022-12-02 17:21:52 +0800702 .fini = osd_hw_fini,
Googler4f18c0c2022-09-20 17:23:36 +0800703};