forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/omapdrm/dss/dispc.c
....@@ -1,21 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2009 Nokia Corporation
34 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
45 *
56 * Some code and ideas taken from drivers/video/omap/ driver
67 * by Imre Deak.
7
- *
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms of the GNU General Public License version 2 as published by
10
- * the Free Software Foundation.
11
- *
12
- * This program is distributed in the hope that it will be useful, but WITHOUT
13
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15
- * more details.
16
- *
17
- * You should have received a copy of the GNU General Public License along with
18
- * this program. If not, see <http://www.gnu.org/licenses/>.
198 */
209
2110 #define DSS_SUBSYS_NAME "DISPC"
....@@ -125,6 +114,7 @@
125114 const unsigned int num_reg_fields;
126115 const enum omap_overlay_caps *overlay_caps;
127116 const u32 **supported_color_modes;
117
+ const u32 *supported_scaler_color_modes;
128118 unsigned int num_mgrs;
129119 unsigned int num_ovls;
130120 unsigned int buffer_size_unit;
....@@ -195,9 +185,6 @@
195185
196186 struct regmap *syscon_pol;
197187 u32 syscon_pol_offset;
198
-
199
- /* DISPC_CONTROL & DISPC_CONFIG lock*/
200
- spinlock_t control_lock;
201188 };
202189
203190 enum omap_color_component {
....@@ -379,25 +366,17 @@
379366 static u32 mgr_fld_read(struct dispc_device *dispc, enum omap_channel channel,
380367 enum mgr_reg_fields regfld)
381368 {
382
- const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
369
+ const struct dispc_reg_field *rfld = &mgr_desc[channel].reg_desc[regfld];
383370
384
- return REG_GET(dispc, rfld.reg, rfld.high, rfld.low);
371
+ return REG_GET(dispc, rfld->reg, rfld->high, rfld->low);
385372 }
386373
387374 static void mgr_fld_write(struct dispc_device *dispc, enum omap_channel channel,
388375 enum mgr_reg_fields regfld, int val)
389376 {
390
- const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
391
- const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG;
392
- unsigned long flags;
377
+ const struct dispc_reg_field *rfld = &mgr_desc[channel].reg_desc[regfld];
393378
394
- if (need_lock) {
395
- spin_lock_irqsave(&dispc->control_lock, flags);
396
- REG_FLD_MOD(dispc, rfld.reg, val, rfld.high, rfld.low);
397
- spin_unlock_irqrestore(&dispc->control_lock, flags);
398
- } else {
399
- REG_FLD_MOD(dispc, rfld.reg, val, rfld.high, rfld.low);
400
- }
379
+ REG_FLD_MOD(dispc, rfld->reg, val, rfld->high, rfld->low);
401380 }
402381
403382 static int dispc_get_num_ovls(struct dispc_device *dispc)
....@@ -414,8 +393,7 @@
414393 enum dispc_feat_reg_field id,
415394 u8 *start, u8 *end)
416395 {
417
- if (id >= dispc->feat->num_reg_fields)
418
- BUG();
396
+ BUG_ON(id >= dispc->feat->num_reg_fields);
419397
420398 *start = dispc->feat->reg_fields[id].start;
421399 *end = dispc->feat->reg_fields[id].end;
....@@ -1138,18 +1116,6 @@
11381116 }
11391117
11401118 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1141
-}
1142
-
1143
-static bool format_is_yuv(u32 fourcc)
1144
-{
1145
- switch (fourcc) {
1146
- case DRM_FORMAT_YUYV:
1147
- case DRM_FORMAT_UYVY:
1148
- case DRM_FORMAT_NV12:
1149
- return true;
1150
- default:
1151
- return false;
1152
- }
11531119 }
11541120
11551121 static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
....@@ -1910,11 +1876,14 @@
19101876 int scale_x = out_width != orig_width;
19111877 int scale_y = out_height != orig_height;
19121878 bool chroma_upscale = plane != OMAP_DSS_WB;
1879
+ const struct drm_format_info *info;
1880
+
1881
+ info = drm_format_info(fourcc);
19131882
19141883 if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
19151884 return;
19161885
1917
- if (!format_is_yuv(fourcc)) {
1886
+ if (!info->is_yuv) {
19181887 /* reset chroma resampling for RGB formats */
19191888 if (plane != OMAP_DSS_WB)
19201889 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
....@@ -2530,6 +2499,19 @@
25302499 if (width == out_width && height == out_height)
25312500 return 0;
25322501
2502
+ if (dispc->feat->supported_scaler_color_modes) {
2503
+ const u32 *modes = dispc->feat->supported_scaler_color_modes;
2504
+ unsigned int i;
2505
+
2506
+ for (i = 0; modes[i]; ++i) {
2507
+ if (modes[i] == fourcc)
2508
+ break;
2509
+ }
2510
+
2511
+ if (modes[i] == 0)
2512
+ return -EINVAL;
2513
+ }
2514
+
25332515 if (plane == OMAP_DSS_WB) {
25342516 switch (fourcc) {
25352517 case DRM_FORMAT_NV12:
....@@ -2624,7 +2606,7 @@
26242606 unsigned int offset0, offset1;
26252607 s32 row_inc;
26262608 s32 pix_inc;
2627
- u16 frame_width, frame_height;
2609
+ u16 frame_width;
26282610 unsigned int field_offset = 0;
26292611 u16 in_height = height;
26302612 u16 in_width = width;
....@@ -2632,6 +2614,9 @@
26322614 bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
26332615 unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
26342616 unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
2617
+ const struct drm_format_info *info;
2618
+
2619
+ info = drm_format_info(fourcc);
26352620
26362621 /* when setting up WB, dispc_plane_pclk_rate() returns 0 */
26372622 if (plane == OMAP_DSS_WB)
....@@ -2640,7 +2625,7 @@
26402625 if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
26412626 return -EINVAL;
26422627
2643
- if (format_is_yuv(fourcc) && (in_width & 1)) {
2628
+ if (info->is_yuv && (in_width & 1)) {
26442629 DSSERR("input width %d is not even for YUV format\n", in_width);
26452630 return -EINVAL;
26462631 }
....@@ -2680,7 +2665,7 @@
26802665 DSSDBG("predecimation %d x %x, new input size %d x %d\n",
26812666 x_predecim, y_predecim, in_width, in_height);
26822667
2683
- if (format_is_yuv(fourcc) && (in_width & 1)) {
2668
+ if (info->is_yuv && (in_width & 1)) {
26842669 DSSDBG("predecimated input width is not even for YUV format\n");
26852670 DSSDBG("adjusting input width %d -> %d\n",
26862671 in_width, in_width & ~1);
....@@ -2688,7 +2673,7 @@
26882673 in_width &= ~1;
26892674 }
26902675
2691
- if (format_is_yuv(fourcc))
2676
+ if (info->is_yuv)
26922677 cconv = 1;
26932678
26942679 if (ilace && !fieldmode) {
....@@ -2714,13 +2699,10 @@
27142699 row_inc = 0;
27152700 pix_inc = 0;
27162701
2717
- if (plane == OMAP_DSS_WB) {
2702
+ if (plane == OMAP_DSS_WB)
27182703 frame_width = out_width;
2719
- frame_height = out_height;
2720
- } else {
2704
+ else
27212705 frame_width = in_width;
2722
- frame_height = height;
2723
- }
27242706
27252707 calc_offset(screen_width, frame_width,
27262708 fourcc, fieldmode, field_offset,
....@@ -2902,13 +2884,6 @@
29022884 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
29032885
29042886 return 0;
2905
-}
2906
-
2907
-static enum omap_dss_output_id
2908
-dispc_mgr_get_supported_outputs(struct dispc_device *dispc,
2909
- enum omap_channel channel)
2910
-{
2911
- return dss_get_supported_outputs(dispc->dss, channel);
29122887 }
29132888
29142889 static void dispc_lcd_enable_signal_polarity(struct dispc_device *dispc,
....@@ -3120,28 +3095,29 @@
31203095 return pclk <= dispc->feat->max_tv_pclk;
31213096 }
31223097
3123
-bool dispc_mgr_timings_ok(struct dispc_device *dispc, enum omap_channel channel,
3124
- const struct videomode *vm)
3098
+static int dispc_mgr_check_timings(struct dispc_device *dispc,
3099
+ enum omap_channel channel,
3100
+ const struct videomode *vm)
31253101 {
31263102 if (!_dispc_mgr_size_ok(dispc, vm->hactive, vm->vactive))
3127
- return false;
3103
+ return MODE_BAD;
31283104
31293105 if (!_dispc_mgr_pclk_ok(dispc, channel, vm->pixelclock))
3130
- return false;
3106
+ return MODE_BAD;
31313107
31323108 if (dss_mgr_is_lcd(channel)) {
31333109 /* TODO: OMAP4+ supports interlace for LCD outputs */
31343110 if (vm->flags & DISPLAY_FLAGS_INTERLACED)
3135
- return false;
3111
+ return MODE_BAD;
31363112
31373113 if (!_dispc_lcd_timings_ok(dispc, vm->hsync_len,
31383114 vm->hfront_porch, vm->hback_porch,
31393115 vm->vsync_len, vm->vfront_porch,
31403116 vm->vback_porch))
3141
- return false;
3117
+ return MODE_BAD;
31423118 }
31433119
3144
- return true;
3120
+ return MODE_OK;
31453121 }
31463122
31473123 static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
....@@ -3161,33 +3137,12 @@
31613137 dispc_write_reg(dispc, DISPC_TIMING_H(channel), timing_h);
31623138 dispc_write_reg(dispc, DISPC_TIMING_V(channel), timing_v);
31633139
3164
- if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
3165
- vs = false;
3166
- else
3167
- vs = true;
3168
-
3169
- if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
3170
- hs = false;
3171
- else
3172
- hs = true;
3173
-
3174
- if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
3175
- de = false;
3176
- else
3177
- de = true;
3178
-
3179
- if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
3180
- ipc = false;
3181
- else
3182
- ipc = true;
3183
-
3184
- /* always use the 'rf' setting */
3185
- onoff = true;
3186
-
3187
- if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
3188
- rf = true;
3189
- else
3190
- rf = false;
3140
+ vs = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
3141
+ hs = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
3142
+ de = !!(vm->flags & DISPLAY_FLAGS_DE_LOW);
3143
+ ipc = !!(vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE);
3144
+ onoff = true; /* always use the 'rf' setting */
3145
+ rf = !!(vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE);
31913146
31923147 l = FLD_VAL(onoff, 17, 17) |
31933148 FLD_VAL(rf, 16, 16) |
....@@ -3243,7 +3198,7 @@
32433198
32443199 DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive);
32453200
3246
- if (!dispc_mgr_timings_ok(dispc, channel, &t)) {
3201
+ if (dispc_mgr_check_timings(dispc, channel, &t)) {
32473202 BUG();
32483203 return;
32493204 }
....@@ -4251,6 +4206,12 @@
42514206 DRM_FORMAT_RGBX8888),
42524207 };
42534208
4209
+static const u32 omap3_dispc_supported_scaler_color_modes[] = {
4210
+ DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_YUYV,
4211
+ DRM_FORMAT_UYVY,
4212
+ 0,
4213
+};
4214
+
42544215 static const struct dispc_features omap24xx_dispc_feats = {
42554216 .sw_start = 5,
42564217 .fp_start = 15,
....@@ -4279,6 +4240,7 @@
42794240 .num_reg_fields = ARRAY_SIZE(omap2_dispc_reg_fields),
42804241 .overlay_caps = omap2_dispc_overlay_caps,
42814242 .supported_color_modes = omap2_dispc_supported_color_modes,
4243
+ .supported_scaler_color_modes = COLOR_ARRAY(DRM_FORMAT_XRGB8888),
42824244 .num_mgrs = 2,
42834245 .num_ovls = 3,
42844246 .buffer_size_unit = 1,
....@@ -4313,6 +4275,7 @@
43134275 .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
43144276 .overlay_caps = omap3430_dispc_overlay_caps,
43154277 .supported_color_modes = omap3_dispc_supported_color_modes,
4278
+ .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes,
43164279 .num_mgrs = 2,
43174280 .num_ovls = 3,
43184281 .buffer_size_unit = 1,
....@@ -4347,6 +4310,7 @@
43474310 .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
43484311 .overlay_caps = omap3430_dispc_overlay_caps,
43494312 .supported_color_modes = omap3_dispc_supported_color_modes,
4313
+ .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes,
43504314 .num_mgrs = 2,
43514315 .num_ovls = 3,
43524316 .buffer_size_unit = 1,
....@@ -4381,6 +4345,7 @@
43814345 .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
43824346 .overlay_caps = omap3630_dispc_overlay_caps,
43834347 .supported_color_modes = omap3_dispc_supported_color_modes,
4348
+ .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes,
43844349 .num_mgrs = 2,
43854350 .num_ovls = 3,
43864351 .buffer_size_unit = 1,
....@@ -4415,6 +4380,7 @@
44154380 .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
44164381 .overlay_caps = omap3430_dispc_overlay_caps,
44174382 .supported_color_modes = omap3_dispc_supported_color_modes,
4383
+ .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes,
44184384 .num_mgrs = 1,
44194385 .num_ovls = 3,
44204386 .buffer_size_unit = 1,
....@@ -4635,11 +4601,10 @@
46354601 i734_buf.size = i734.ovli.width * i734.ovli.height *
46364602 color_mode_to_bpp(i734.ovli.fourcc) / 8;
46374603
4638
- i734_buf.vaddr = dma_alloc_writecombine(&dispc->pdev->dev,
4639
- i734_buf.size, &i734_buf.paddr,
4640
- GFP_KERNEL);
4604
+ i734_buf.vaddr = dma_alloc_wc(&dispc->pdev->dev, i734_buf.size,
4605
+ &i734_buf.paddr, GFP_KERNEL);
46414606 if (!i734_buf.vaddr) {
4642
- dev_err(&dispc->pdev->dev, "%s: dma_alloc_writecombine failed\n",
4607
+ dev_err(&dispc->pdev->dev, "%s: dma_alloc_wc failed\n",
46434608 __func__);
46444609 return -ENOMEM;
46454610 }
....@@ -4652,8 +4617,8 @@
46524617 if (!dispc->feat->has_gamma_i734_bug)
46534618 return;
46544619
4655
- dma_free_writecombine(&dispc->pdev->dev, i734_buf.size, i734_buf.vaddr,
4656
- i734_buf.paddr);
4620
+ dma_free_wc(&dispc->pdev->dev, i734_buf.size, i734_buf.vaddr,
4621
+ i734_buf.paddr);
46574622 }
46584623
46594624 static void dispc_errata_i734_wa(struct dispc_device *dispc)
....@@ -4740,9 +4705,9 @@
47404705 .mgr_go_busy = dispc_mgr_go_busy,
47414706 .mgr_go = dispc_mgr_go,
47424707 .mgr_set_lcd_config = dispc_mgr_set_lcd_config,
4708
+ .mgr_check_timings = dispc_mgr_check_timings,
47434709 .mgr_set_timings = dispc_mgr_set_timings,
47444710 .mgr_setup = dispc_mgr_setup,
4745
- .mgr_get_supported_outputs = dispc_mgr_get_supported_outputs,
47464711 .mgr_gamma_size = dispc_mgr_gamma_size,
47474712 .mgr_set_gamma = dispc_mgr_set_gamma,
47484713
....@@ -4794,8 +4759,6 @@
47944759 dispc->pdev = pdev;
47954760 platform_set_drvdata(pdev, dispc);
47964761 dispc->dss = dss;
4797
-
4798
- spin_lock_init(&dispc->control_lock);
47994762
48004763 /*
48014764 * The OMAP3-based models can't be told apart using the compatible
....@@ -4952,6 +4915,7 @@
49524915 static const struct dev_pm_ops dispc_pm_ops = {
49534916 .runtime_suspend = dispc_runtime_suspend,
49544917 .runtime_resume = dispc_runtime_resume,
4918
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
49554919 };
49564920
49574921 struct platform_driver omap_dispchw_driver = {