Re: [PATCH] drm/gma500: Fix comment typo

2022-08-29 Thread Patrik Jakobsson
On Thu, Aug 4, 2022 at 1:48 PM Jason Wang  wrote:
>
> The double `the' is duplicated in the comment, remove one.
>
> Signed-off-by: Jason Wang 

Pushed to drm-misc-next

Thanks
Patrik

> ---
>  drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c 
> b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> index bb2e9d64018a..53b967282d6a 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> @@ -115,7 +115,7 @@ i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool 
> reading)
>
>  /*
>   * Write a single byte to the current I2C address, the
> - * the I2C link must be running or this returns -EIO
> + * I2C link must be running or this returns -EIO
>   */
>  static int
>  i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
> --
> 2.35.1
>


Re: [PATCH] tty/vt: Remove printable variable

2022-08-29 Thread Jiri Slaby

On 26. 08. 22, 22:24, Daniel Vetter wrote:

Every since the 0.99.7A release when console_register() was introduced
it's become impossible to call vt_console_print (called
console_print() back then still) directly. Which means the
initialization issue this variable protected against is no more.

Give it a send off with style and let it rest in peace.


FWIW:
Reviewed-by: Jiri Slaby 

In hopes, nothing breaks.


Signed-off-by: Daniel Vetter 
Cc: Greg Kroah-Hartman 
Cc: Jiri Slaby 
Cc: "Ilpo Järvinen" 
Cc: nick black 
Cc: Daniel Vetter 
Cc: Tetsuo Handa 
Cc: Yangxi Xiang 
Cc: Xuezhi Zhang 
---
  drivers/tty/vt/vt.c | 4 
  1 file changed, 4 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index ae9c926acd6f..4d29e4a17db7 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -157,7 +157,6 @@ static void set_palette(struct vc_data *vc);
  
  #define vt_get_kmsg_redirect() vt_kmsg_redirect(-1)
  
-static int printable;		/* Is console ready for printing? */

  int default_utf8 = true;
  module_param(default_utf8, int, S_IRUGO | S_IWUSR);
  int global_cursor_default = -1;
@@ -3085,8 +3084,6 @@ static void vt_console_print(struct console *co, const 
char *b, unsigned count)
int kmsg_console;
  
  	/* console busy or not yet initialized */

-   if (!printable)
-   return;
if (!spin_trylock(&printing_lock))
return;
  
@@ -3537,7 +3534,6 @@ static int __init con_init(void)

pr_info("Console: %s %s %dx%d\n",
vc->vc_can_do_color ? "colour" : "mono",
display_desc, vc->vc_cols, vc->vc_rows);
-   printable = 1;
  
  	console_unlock();
  


thanks,
--
js
suse labs



Re: [PATCH v1 05/35] drm/connector: Add TV standard property

2022-08-29 Thread Maxime Ripard
On Thu, Aug 25, 2022 at 05:13:29PM +0200, Noralf Trønnes wrote:
> 
> 
> Den 25.08.2022 15.44, skrev Maxime Ripard:
> > Hi,
> > 
> > On Sat, Aug 20, 2022 at 10:12:46PM +0200, Noralf Trønnes wrote:
> >>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> >>> index 1e9996b33cc8..78275e68ff66 100644
> >>> --- a/include/drm/drm_connector.h
> >>> +++ b/include/drm/drm_connector.h
> >>> @@ -143,6 +143,32 @@ enum subpixel_order {
> >>>  
> >>>  };
> >>>  
> >>> +#define DRM_MODE_TV_NORM_NTSC_443(1 << 0)
> >>> +#define DRM_MODE_TV_NORM_NTSC_J  (1 << 1)
> >>> +#define DRM_MODE_TV_NORM_NTSC_M  (1 << 2)
> >>> +#define DRM_MODE_TV_NORM_PAL_60  (1 << 3)
> >>> +#define DRM_MODE_TV_NORM_PAL_B   (1 << 4)
> >>> +#define DRM_MODE_TV_NORM_PAL_D   (1 << 5)
> >>> +#define DRM_MODE_TV_NORM_PAL_G   (1 << 6)
> >>> +#define DRM_MODE_TV_NORM_PAL_H   (1 << 7)
> >>> +#define DRM_MODE_TV_NORM_PAL_I   (1 << 8)
> >>> +#define DRM_MODE_TV_NORM_PAL_M   (1 << 9)
> >>> +#define DRM_MODE_TV_NORM_PAL_N   (1 << 10)
> >>> +#define DRM_MODE_TV_NORM_PAL_NC  (1 << 11)
> >>> +#define DRM_MODE_TV_NORM_SECAM_60(1 << 12)
> >>> +#define DRM_MODE_TV_NORM_SECAM_B (1 << 13)
> >>> +#define DRM_MODE_TV_NORM_SECAM_D (1 << 14)
> >>> +#define DRM_MODE_TV_NORM_SECAM_G (1 << 15)
> >>> +#define DRM_MODE_TV_NORM_SECAM_K (1 << 16)
> >>> +#define DRM_MODE_TV_NORM_SECAM_K1(1 << 17)
> >>> +#define DRM_MODE_TV_NORM_SECAM_L (1 << 18)
> >>> +#define DRM_MODE_TV_NORM_HD480I  (1 << 19)
> >>> +#define DRM_MODE_TV_NORM_HD480P  (1 << 20)
> >>> +#define DRM_MODE_TV_NORM_HD576I  (1 << 21)
> >>> +#define DRM_MODE_TV_NORM_HD576P  (1 << 22)
> >>> +#define DRM_MODE_TV_NORM_HD720P  (1 << 23)
> >>> +#define DRM_MODE_TV_NORM_HD1080I (1 << 24)
> >>> +
> >>
> >> This is an area where DRM overlaps with v4l2, see:
> >> - include/dt-bindings/display/sdtv-standards.h
> >> - v4l2_norm_to_name()
> >>
> >> Maybe we should follow suit, but if we do our own thing please mention
> >> why in the commit message.
> > 
> > Are you suggesting that we'd share that definition with v4l2?
> > 
> 
> If possible, yes.
> 
> > I've tried to share some code in the past between v4l2 and DRM, and it
> > got completely shut down so it's not something I'd like to try again, if
> > possible.
> > 
> 
> But that is a good enough reason not to do so. I just got the impression
> from some of Laurent's emails a while back that there was some
> cooperativ atmosphere, but I might be mistaken in my reading/understanding.

Here's the original thread:
https://lore.kernel.org/lkml/cover.8ec406bf8f4f097e9dc909d5aac466556822f592.1555487650.git-series.maxime.rip...@bootlin.com/

It ended up stalling completely, without any will from either DRM or
v4l2 to get this through. So I will not work on anything like that until
both maintainership teams have expressed that it's something they
actually want.

> It is ofc possible to just copy the values from sdtv-standards.h, but I
> see that hd* is missing from that list, so not sure if there's much
> point if it has to be extended without changing the source.

HD formats were dropped, so it's not a big deal. However, we are missing
a few formats, but that were never used by either nouveau, i915 or any
other driver. I'm not sure it's worth adding at that point, and we can
always extend it later.

Maxime


signature.asc
Description: PGP signature


Re: [Intel-gfx] [PATCH 03/11] drm/edid: s/monitor_rage/vrr_range/

2022-08-29 Thread Jani Nikula
On Sat, 27 Aug 2022, Ville Syrjala  wrote:
> From: Ville Syrjälä 
>
> Rename info->monitor_range to info->vrr_range to actually
> reflect its usage.
>
> Cc: Manasi Navare 
> Cc: Nicholas Kazlauskas 
> Cc: Harry Wentland 
> Cc: Leo Li 
> Cc: Rodrigo Siqueira 
> Cc: amd-...@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä 
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 -
>  drivers/gpu/drm/drm_debugfs.c |  4 +--
>  drivers/gpu/drm/drm_edid.c| 26 +--
>  drivers/gpu/drm/i915/display/intel_vrr.c  |  6 ++---
>  include/drm/drm_connector.h   |  4 +--
>  5 files changed, 26 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index e702f0d72d53..928b5b6541db 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -9921,8 +9921,8 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>   amdgpu_dm_connector->min_vfreq = 0;
>   amdgpu_dm_connector->max_vfreq = 0;
>   amdgpu_dm_connector->pixel_clock_mhz = 0;
> - connector->display_info.monitor_range.min_vfreq = 0;
> - connector->display_info.monitor_range.max_vfreq = 0;
> + connector->display_info.vrr_range.min_vfreq = 0;
> + connector->display_info.vrr_range.max_vfreq = 0;
>   freesync_capable = false;
>  
>   goto update;
> @@ -9970,8 +9970,8 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>   amdgpu_dm_connector->pixel_clock_mhz =
>   range->pixel_clock_mhz * 10;
>  
> - connector->display_info.monitor_range.min_vfreq 
> = range->min_vfreq;
> - connector->display_info.monitor_range.max_vfreq 
> = range->max_vfreq;
> + connector->display_info.vrr_range.min_vfreq = 
> range->min_vfreq;
> + connector->display_info.vrr_range.max_vfreq = 
> range->max_vfreq;
>  
>   break;
>   }
> @@ -9993,8 +9993,8 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>   if (amdgpu_dm_connector->max_vfreq - 
> amdgpu_dm_connector->min_vfreq > 10)
>   freesync_capable = true;
>  
> - connector->display_info.monitor_range.min_vfreq = 
> vsdb_info.min_refresh_rate_hz;
> - connector->display_info.monitor_range.max_vfreq = 
> vsdb_info.max_refresh_rate_hz;
> + connector->display_info.vrr_range.min_vfreq = 
> vsdb_info.min_refresh_rate_hz;
> + connector->display_info.vrr_range.max_vfreq = 
> vsdb_info.max_refresh_rate_hz;
>   }
>   }

The amdgpu changes really beg the question why they're filling up
display_info themselves instead of relying on drm_edid.c to do that for
them.

Other than that,

Acked-by: Jani Nikula 


>  
> diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
> index 01ee3febb813..1437c798b122 100644
> --- a/drivers/gpu/drm/drm_debugfs.c
> +++ b/drivers/gpu/drm/drm_debugfs.c
> @@ -377,8 +377,8 @@ static int vrr_range_show(struct seq_file *m, void *data)
>   if (connector->status != connector_status_connected)
>   return -ENODEV;
>  
> - seq_printf(m, "Min: %u\n", 
> connector->display_info.monitor_range.min_vfreq);
> - seq_printf(m, "Max: %u\n", 
> connector->display_info.monitor_range.max_vfreq);
> + seq_printf(m, "Min: %u\n", connector->display_info.vrr_range.min_vfreq);
> + seq_printf(m, "Max: %u\n", connector->display_info.vrr_range.max_vfreq);
>  
>   return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index ac662495635c..4355d73632c3 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -6020,11 +6020,11 @@ static void drm_parse_cea_ext(struct drm_connector 
> *connector,
>  }
>  
>  static
> -void get_monitor_range(const struct detailed_timing *timing, void *c)
> +void get_vrr_range(const struct detailed_timing *timing, void *c)
>  {
>   struct detailed_mode_closure *closure = c;
>   struct drm_display_info *info = &closure->connector->display_info;
> - struct drm_monitor_range_info *monitor_range = &info->monitor_range;
> + struct drm_monitor_range_info *vrr_range = &info->vrr_range;
>   const struct detailed_non_pixel *data = &timing->data.other_data;
>   const struct detailed_data_monitor_range *range = &data->data.range;
>   const struct edid *edid = closure->drm_edid->edid;
> @@ -6044,19 +6044,19 @@ void get_monitor_range(const struct detailed_timing 
> *timing, void *c)
>   if (range->flags != DRM_EDID_RANGE

[PATCH -next 1/4 RESEND] drm/amd/display: clean up one inconsistent indenting

2022-08-29 Thread Yang Li
1. The indentation of statements in the same curly bracket should be
consistent.
2. Variable declarations in the same function should be aligned.

Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1887
Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1888
Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1889
Reported-by: Abaci Robot 
Signed-off-by: Yang Li 
---
 .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c| 13 -
 .../amd/display/dc/dml/dcn32/display_mode_vba_32.c  |  6 +++---
 .../display/dc/dml/dcn32/display_mode_vba_util_32.c |  2 +-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index edefb3fc1c3c..25406e00da49 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -2141,13 +2141,16 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, 
struct clk_bw_params *bw_pa
 
if 
(dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == 
BP_RESULT_OK) {
if (bb_info.dram_clock_change_latency_100ns > 0)
-   dcn3_2_soc.dram_clock_change_latency_us 
= bb_info.dram_clock_change_latency_100ns * 10;
+   dcn3_2_soc.dram_clock_change_latency_us 
=
+   
bb_info.dram_clock_change_latency_100ns * 10;
 
-   if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
-   dcn3_2_soc.sr_enter_plus_exit_time_us = 
bb_info.dram_sr_enter_exit_latency_100ns * 10;
+   if (bb_info.dram_sr_enter_exit_latency_100ns > 
0)
+   dcn3_2_soc.sr_enter_plus_exit_time_us =
+   
bb_info.dram_sr_enter_exit_latency_100ns * 10;
 
-   if (bb_info.dram_sr_exit_latency_100ns > 0)
-   dcn3_2_soc.sr_exit_time_us = 
bb_info.dram_sr_exit_latency_100ns * 10;
+   if (bb_info.dram_sr_exit_latency_100ns > 0)
+   dcn3_2_soc.sr_exit_time_us =
+   
bb_info.dram_sr_exit_latency_100ns * 10;
}
}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
index cb2025771646..6a4f730419c0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
@@ -677,9 +677,9 @@ static void 
DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
dml_ceil((double) 
v->WritebackDelay[mode_lib->vba.VoltageLevel][k]
/ (mode_lib->vba.HTotal[k] / 
mode_lib->vba.PixelClock[k]), 1));
 
-   // Clamp to max OTG vstartup register limit
-   if (v->MaxVStartupLines[k] > 1023)
-   v->MaxVStartupLines[k] = 1023;
+   // Clamp to max OTG vstartup register limit
+   if (v->MaxVStartupLines[k] > 1023)
+   v->MaxVStartupLines[k] = 1023;
 
 #ifdef __DML_VBA_DEBUG__
dml_print("DML::%s: k=%d MaxVStartupLines = %d\n", __func__, k, 
v->MaxVStartupLines[k]);
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
index 05fc14a47fba..5a6b893f7295 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
@@ -4277,7 +4277,7 @@ void 
dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
double ActiveClockChangeLatencyHidingY;
double ActiveClockChangeLatencyHidingC;
double ActiveClockChangeLatencyHiding;
-double EffectiveDETBufferSizeY;
+   double EffectiveDETBufferSizeY;
double ActiveFCLKChangeLatencyMargin[DC__NUM_DPP__MAX];
double USRRetrainingLatencyMargin[DC__NUM_DPP__MAX];
double TotalPixelBW = 0.0;
-- 
2.20.1.7.g153144c



[PATCH -next 4/4 RESEND] drm/amd/display: clean up some inconsistent indentings

2022-08-29 Thread Yang Li
The indentation of statements in the same curly bracket should be
consistent.

Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1892
Reported-by: Abaci Robot 
Signed-off-by: Yang Li 
---
 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
index 3b1c6603ae0c..c2d76cec29ba 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -641,9 +641,9 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params;
-/* there are no ROM LUTs in OUTGAM */
-   if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
-   BREAK_TO_DEBUGGER();
+   /* there are no ROM LUTs in OUTGAM */
+   if (stream->out_transfer_func->type == 
TF_TYPE_PREDEFINED)
+   BREAK_TO_DEBUGGER();
}
}
 
-- 
2.20.1.7.g153144c



[PATCH -next 3/4 RESEND] drm/amd/display: clean up some inconsistent indentings

2022-08-29 Thread Yang Li
The indentation of statements in the same curly bracket should be
consistent.

Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1890
Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1891
Reported-by: Abaci Robot 
Signed-off-by: Yang Li 
---
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 +--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 37246e965457..66e6c070a463 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -2151,8 +2151,8 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int 
group_size,

dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
dc->res_pool->dp_clock_source,
grouped_pipes[i]->stream_res.tg->inst, 
&pclk);
-   
grouped_pipes[i]->stream->timing.pix_clk_100hz =
-   
pclk*get_clock_divider(grouped_pipes[i], false);
+   grouped_pipes[i]->stream->timing.pix_clk_100hz =
+   
pclk*get_clock_divider(grouped_pipes[i], false);
if (master == -1)
master = i;
}
@@ -2199,14 +2199,14 @@ void dcn10_enable_vblanks_synchronization(
if (master >= 0) {
for (i = 0; i < group_size; i++) {
if (i != master && 
!grouped_pipes[i]->stream->has_non_synchronizable_pclk)
-   grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
-   grouped_pipes[master]->stream_res.tg,
-   grouped_pipes[i]->stream_res.tg,
-   
grouped_pipes[master]->stream->timing.pix_clk_100hz,
-   grouped_pipes[i]->stream->timing.pix_clk_100hz,
-   get_clock_divider(grouped_pipes[master], false),
-   get_clock_divider(grouped_pipes[i], false));
-   grouped_pipes[i]->stream->vblank_synchronized = 
true;
+   
grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
+   grouped_pipes[master]->stream_res.tg,
+   grouped_pipes[i]->stream_res.tg,
+   
grouped_pipes[master]->stream->timing.pix_clk_100hz,
+   
grouped_pipes[i]->stream->timing.pix_clk_100hz,
+   
get_clock_divider(grouped_pipes[master], false),
+   get_clock_divider(grouped_pipes[i], 
false));
+   grouped_pipes[i]->stream->vblank_synchronized = true;
}
grouped_pipes[master]->stream->vblank_synchronized = true;
DC_SYNC_INFO("Sync complete\n");
-- 
2.20.1.7.g153144c



[PATCH -next 2/4 RESEND] drm/amd/display: clean up some inconsistent indentings

2022-08-29 Thread Yang Li
The indentation of statements in the same curly bracket should be
consistent.

Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1886
Reported-by: Abaci Robot 
Signed-off-by: Yang Li 
---
 .../gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c  | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
index c87091683b5d..7ebf25e87933 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
@@ -518,13 +518,16 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, 
struct clk_bw_params *bw_p
 
if 
(dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == 
BP_RESULT_OK) {
if (bb_info.dram_clock_change_latency_100ns > 0)
-   
dcn3_21_soc.dram_clock_change_latency_us = 
bb_info.dram_clock_change_latency_100ns * 10;
+   
dcn3_21_soc.dram_clock_change_latency_us =
+   
bb_info.dram_clock_change_latency_100ns * 10;
 
-   if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
-   dcn3_21_soc.sr_enter_plus_exit_time_us = 
bb_info.dram_sr_enter_exit_latency_100ns * 10;
+   if (bb_info.dram_sr_enter_exit_latency_100ns > 
0)
+   dcn3_21_soc.sr_enter_plus_exit_time_us =
+   
bb_info.dram_sr_enter_exit_latency_100ns * 10;
 
-   if (bb_info.dram_sr_exit_latency_100ns > 0)
-   dcn3_21_soc.sr_exit_time_us = 
bb_info.dram_sr_exit_latency_100ns * 10;
+   if (bb_info.dram_sr_exit_latency_100ns > 0)
+   dcn3_21_soc.sr_exit_time_us =
+   
bb_info.dram_sr_exit_latency_100ns * 10;
}
}
 
-- 
2.20.1.7.g153144c



Re: [Intel-gfx] [PATCH 04/11] drm/edid: Define more flags

2022-08-29 Thread Jani Nikula
On Sat, 27 Aug 2022, Ville Syrjala  wrote:
> From: Ville Syrjälä 
>
> Replace a bunch of hex constants with proper definitions.
>
> Signed-off-by: Ville Syrjälä 

Reviewed-by: Jani Nikula 

> ---
>  drivers/gpu/drm/drm_edid.c | 18 +-
>  include/drm/drm_edid.h | 14 +-
>  2 files changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 4355d73632c3..856d304a1354 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2984,7 +2984,7 @@ is_rb(const struct detailed_timing *descriptor, void 
> *data)
>   BUILD_BUG_ON(offsetof(typeof(*descriptor), 
> data.other_data.data.range.formula.cvt.flags) != 15);
>  
>   if (descriptor->data.other_data.data.range.flags == 
> DRM_EDID_CVT_SUPPORT_FLAG &&
> - descriptor->data.other_data.data.range.formula.cvt.flags & 0x10)
> + descriptor->data.other_data.data.range.formula.cvt.flags & 
> DRM_EDID_CVT_FLAGS_REDUCED_BLANKING)
>   *res = true;
>  }
>  
> @@ -3012,7 +3012,7 @@ find_gtf2(const struct detailed_timing *descriptor, 
> void *data)
>  
>   BUILD_BUG_ON(offsetof(typeof(*descriptor), 
> data.other_data.data.range.flags) != 10);
>  
> - if (descriptor->data.other_data.data.range.flags == 0x02)
> + if (descriptor->data.other_data.data.range.flags == 
> DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG)
>   *res = descriptor;
>  }
>  
> @@ -3415,7 +3415,7 @@ range_pixel_clock(const struct edid *edid, const u8 *t)
>   return 0;
>  
>   /* 1.4 with CVT support gives us real precision, yay */
> - if (edid->revision >= 4 && t[10] == 0x04)
> + if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
>   return (t[9] * 1) - ((t[12] >> 2) * 250);
>  
>   /* 1.3 is pathetic, so fuzz up a bit */
> @@ -3441,7 +3441,7 @@ static bool mode_in_range(const struct drm_display_mode 
> *mode,
>   return false;
>  
>   /* 1.4 max horizontal check */
> - if (edid->revision >= 4 && t[10] == 0x04)
> + if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
>   if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3
>   return false;
>  
> @@ -3581,13 +3581,13 @@ do_inferred_modes(const struct detailed_timing 
> *timing, void *c)
>   return; /* GTF not defined yet */
>  
>   switch (range->flags) {
> - case 0x02: /* secondary gtf, XXX could do more */
> - case 0x00: /* default gtf */
> + case DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG: /* XXX could do more */
> + case DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG:
>   closure->modes += drm_gtf_modes_for_range(closure->connector,
> closure->drm_edid,
> timing);
>   break;
> - case 0x04: /* cvt, only in 1.4+ */
> + case DRM_EDID_CVT_SUPPORT_FLAG:
>   if (!version_greater(closure->drm_edid, 1, 3))
>   break;
>  
> @@ -3595,7 +3595,7 @@ do_inferred_modes(const struct detailed_timing *timing, 
> void *c)
> closure->drm_edid,
> timing);
>   break;
> - case 0x01: /* just the ranges, no formula */
> + case DRM_EDID_RANGE_LIMITS_ONLY_FLAG:
>   default:
>   break;
>   }
> @@ -6393,7 +6393,7 @@ static int _drm_edid_connector_update(struct 
> drm_connector *connector,
>   num_modes += add_cea_modes(connector, drm_edid);
>   num_modes += add_alternate_cea_modes(connector, drm_edid);
>   num_modes += add_displayid_detailed_modes(connector, drm_edid);
> - if (drm_edid->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
> + if (drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ)
>   num_modes += add_inferred_modes(connector, drm_edid);
>  
>   if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 1ed61e2b30a4..429735b91f63 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -97,10 +97,13 @@ struct detailed_data_string {
>  #define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) /* 1.4 */
>  #define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) /* 1.4 */
>  
> -#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG   0x00
> -#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01
> -#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02
> -#define DRM_EDID_CVT_SUPPORT_FLAG   0x04
> +#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG   0x00 /* 1.3 */
> +#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 /* 1.4 */
> +#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 /* 1.3 */
> +#define DRM_EDID_CVT_SUPPORT_FLAG   0x04 /* 1.4 */
> +
> +#define DRM_EDID_CVT_FLAGS_STANDARD_BLANKING (1 << 3)
> +#define DRM_EDID_CVT_FLAGS

Re: [Intel-gfx] [PATCH 06/11] drm/edid: Extract drm_gtf2_mode()

2022-08-29 Thread Jani Nikula
On Sat, 27 Aug 2022, Ville Syrjala  wrote:
> From: Ville Syrjälä 
>
> Extract the GTF vs. GTF2 logic into a separate function.
> We'll have a second user soon.
>
> Signed-off-by: Ville Syrjälä 

Reviewed-by: Jani Nikula 

> ---
>  drivers/gpu/drm/drm_edid.c | 47 --
>  1 file changed, 30 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index b459fdf12b58..0c7cbe9b44f5 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3113,6 +3113,35 @@ static int drm_mode_hsync(const struct 
> drm_display_mode *mode)
>   return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);
>  }
>  
> +static struct drm_display_mode *
> +drm_gtf2_mode(struct drm_device *dev,
> +   const struct drm_edid *drm_edid,
> +   int hsize, int vsize, int vrefresh_rate)
> +{
> + struct drm_display_mode *mode;
> +
> + /*
> +  * This is potentially wrong if there's ever a monitor with
> +  * more than one ranges section, each claiming a different
> +  * secondary GTF curve.  Please don't do that.
> +  */
> + mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
> + if (!mode)
> + return NULL;
> +
> + if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
> + drm_mode_destroy(dev, mode);
> + mode = drm_gtf_mode_complex(dev, hsize, vsize,
> + vrefresh_rate, 0, 0,
> + drm_gtf2_m(drm_edid),
> + drm_gtf2_2c(drm_edid),
> + drm_gtf2_k(drm_edid),
> + drm_gtf2_2j(drm_edid));
> + }
> +
> + return mode;
> +}
> +
>  /*
>   * Take the standard timing params (in this case width, aspect, and refresh)
>   * and convert them into a real mode using CVT/GTF/DMT.
> @@ -3201,23 +3230,7 @@ static struct drm_display_mode *drm_mode_std(struct 
> drm_connector *connector,
>   mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
>   break;
>   case LEVEL_GTF2:
> - /*
> -  * This is potentially wrong if there's ever a monitor with
> -  * more than one ranges section, each claiming a different
> -  * secondary GTF curve.  Please don't do that.
> -  */
> - mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
> - if (!mode)
> - return NULL;
> - if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
> - drm_mode_destroy(dev, mode);
> - mode = drm_gtf_mode_complex(dev, hsize, vsize,
> - vrefresh_rate, 0, 0,
> - drm_gtf2_m(drm_edid),
> - drm_gtf2_2c(drm_edid),
> - drm_gtf2_k(drm_edid),
> - drm_gtf2_2j(drm_edid));
> - }
> + mode = drm_gtf2_mode(dev, drm_edid, hsize, vsize, 
> vrefresh_rate);
>   break;
>   case LEVEL_CVT:
>   mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [Intel-gfx] [PATCH 11/11] drm/i915: Infer vrefresh range for eDP if the EDID omits it

2022-08-29 Thread Jani Nikula
On Sat, 27 Aug 2022, Ville Syrjala  wrote:
> From: Ville Syrjälä 
>
> A bunch of machines seem to have eDP panels where the EDID
> indicates continuous frequency support but fails to actually
> include the range descirptor. This violates the EDID 1.4
> spec, but looks like the Windows driver just hacks around
> this by just assuming that the panel supports a continuous
> refresh rate range that covers all EDID reported modes.
>
> Do the same so that we get VRR support on these machines.
>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6323
> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 45 +
>  1 file changed, 45 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 8d1559323412..1f3e4824d316 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -5207,6 +5207,49 @@ intel_edp_add_properties(struct intel_dp *intel_dp)
>  fixed_mode->vdisplay);
>  }
>  
> +/*
> + * Some VRR eDP panels violate the EDID spec and neglect
> + * to include the monitor range descriptor in the EDID.
> + * Cook up the VRR refresh rate limits based on the modes
> + * reported by the panel.
> + */
> +static void
> +intel_edp_infer_vrr_range(struct intel_connector *connector)
> +{
> + struct drm_i915_private *i915 = to_i915(connector->base.dev);
> + struct drm_display_info *info = &connector->base.display_info;
> + const struct edid *edid = connector->edid;
> + const struct drm_display_mode *mode;
> +
> + if (!HAS_VRR(i915))
> + return;
> +
> + if (!edid || edid->revision < 4 ||

connector->edid is actually an error pointer. I made it so way back when
to differentiate between "broken edid" -EINVAL and "no edid" -ENOENT,
but I don't think we ever use that distinction anywhere.

Either ditch the error pointers (in a separate patch) or check for them
here. With that fixed,

Reviewed-by: Jani Nikula 


> + !(edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) ||
> + info->vrr_range.min_vfreq || info->vrr_range.max_vfreq)
> + return;
> +
> + if (list_empty(&connector->base.probed_modes))
> + return;
> +
> + info->vrr_range.min_vfreq = ~0;
> + info->vrr_range.max_vfreq = 0;
> +
> + list_for_each_entry(mode, &connector->base.probed_modes, head) {
> + int vrefresh = drm_mode_vrefresh(mode);
> +
> + info->vrr_range.min_vfreq = min_t(int, vrefresh,
> +   info->vrr_range.min_vfreq);
> + info->vrr_range.max_vfreq = max_t(int, vrefresh,
> +   info->vrr_range.max_vfreq);
> + }
> +
> + drm_dbg_kms(&i915->drm,
> + "[CONNECTOR:%d:%s] does not report refresh rate range, 
> assuming: %d Hz - %d Hz\n",
> + connector->base.base.id, connector->base.name,
> + info->vrr_range.min_vfreq, info->vrr_range.max_vfreq);
> +}
> +
>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>struct intel_connector *intel_connector)
>  {
> @@ -5271,6 +5314,8 @@ static bool intel_edp_init_connector(struct intel_dp 
> *intel_dp,
>   }
>   intel_connector->edid = edid;
>  
> + intel_edp_infer_vrr_range(intel_connector);
> +
>   intel_bios_init_panel(dev_priv, &intel_connector->panel,
> encoder->devdata, IS_ERR(edid) ? NULL : edid);

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH 05/11] drm/edid: Only parse VRR range for continuous frequency displays

2022-08-29 Thread Jani Nikula
On Sat, 27 Aug 2022, Ville Syrjala  wrote:
> From: Ville Syrjälä 
>
> Since we only use the parsed vrefresh range to determine
> if VRR should be supported we should only accept continuous
> frequency displays here.
>
> Cc: Manasi Navare 
> Cc: Nicholas Kazlauskas 
> Cc: Harry Wentland 
> Cc: Leo Li 
> Cc: Rodrigo Siqueira 
> Cc: amd-...@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä 

Makes sense, at least for sane EDIDs. :p

Reviewed-by: Jani Nikula 

> ---
>  drivers/gpu/drm/drm_edid.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 856d304a1354..b459fdf12b58 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -6064,7 +6064,10 @@ static void drm_get_vrr_range(struct drm_connector 
> *connector,
>   .drm_edid = drm_edid,
>   };
>  
> - if (!version_greater(drm_edid, 1, 1))
> + if (!version_greater(drm_edid, 1, 3))
> + return;
> +
> + if (!(drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ))
>   return;
>  
>   drm_for_each_detailed_block(drm_edid, get_vrr_range, &closure);

-- 
Jani Nikula, Intel Open Source Graphics Center


[PATCH v6 0/2] Add RZ/G2L DSI driver

2022-08-29 Thread Biju Das
This patch series aims to support the MIPI DSI encoder found in the RZ/G2L
SoC. It currently supports DSI video mode only.

This unit supports MIPI Alliance Specification for Display Serial Interface 
(DSI)
Specification. This unit provides a solution for transmitting MIPI DSI compliant
digital video and packets. Normative References are below.
* MIPI Alliance Specification for Display Serial Interface Version 1.3.1
* MIPI Alliance Specification for D-PHY Version 2.1

The following are key features of this unit.

* 1 channel
* The number of Lane: 4-lane
* Support up to Full HD (1920 × 1080), 60 fps (RGB888)
* Maximum Bandwidth: 1.5 Gbps per lane
* Support Output Data Format: RGB666 / RGB888

v5->v6:
 * Updated commit description
 * Moved handling of arst and prst from rzg2l_mipi_dsi_startup->runtime
   PM suspend/resume handlers.
 * Max lane capability read at probe(), and enforced in
   rzg2l_mipi_dsi_host_attach()
 * Simplified vich1ppsetr setting.
 * Renamed hsclk_running_mode,hsclk_mode->is_clk_cont.
 * Fixed typo in probe error message(arst->rst).
 * Reordered DRM bridge initaization in probe()
 * Updated typo in e-mail address.
v4->v5:
 * Added Ack from Sam.
 * Added a trivial change, replaced rzg2l_mipi_dsi_parse_dt()
   with drm_of_get_data_lanes_count_ep() in probe.
v3->v4:
 * Updated error handling in rzg2l_mipi_dsi_startup() and 
rzg2l_mipi_dsi_atomic_enable().
v2->v3:
 * Added Rb tag from Geert and Laurent
 * Fixed the typo "Receive" -> "transmit"
 * Added accepible values for data-lanes
 * Sorted Header file in the example
 * Added SoC specific compaible along with generic one.
 * pass rzg2l_mipi_dsi pointer to {Link,Phy} register rd/wr function instead
   of the memory pointer
 * Fixed the comment in rzg2l_mipi_dsi_startup()
 * Removed unnecessary dbg message from rzg2l_mipi_dsi_start_video()
 * DRM bridge parameter initialization moved to probe
 * Replaced dev_dbg->dev_err in rzg2l_mipi_dsi_parse_dt()
 * Inserted the missing blank lane after return in probe()
 * Added missing MODULE_DEVICE_TABLE
 * Added include linux/bits.h in header file
 * Fixed various macros in header file.
 * Reorder the make file for DSI, so that it is no more dependent
   on RZ/G2L DU patch series.
v1->v2:
 * Added full path for dsi-controller.yaml
 * Modeled DSI + D-PHY as single block and updated reg property
 * Fixed typo D_PHY->D-PHY
 * Updated description
 * Added interrupts and interrupt-names and updated the example 
 * Driver rework based on dt-binding changes (DSI + D-PHY) as single block
 * Replaced link_mmio and phy_mmio with mmio in struct rzg2l_mipi_dsi
 * Replaced rzg2l_mipi_phy_write with rzg2l_mipi_dsi_phy_write
   and rzg2l_mipi_dsi_link_write
 * Replaced rzg2l_mipi_phy_read->rzg2l_mipi_dsi_link_read
RFC->v1:
 * Added a ref to dsi-controller.yaml.
 * Added "depends on ARCH_RENESAS || COMPILE_TEST" on KCONFIG
   and dropped DRM as it is implied by DRM_BRIDGE
 * Used devm_reset_control_get_exclusive() for reset handle
 * Removed bool hsclkmode from struct rzg2l_mipi_dsi
 * Added error check for pm, using pm_runtime_resume_and_get() instead of
   pm_runtime_get_sync()
 * Added check for unsupported formats in rzg2l_mipi_dsi_host_attach()
 * Avoided read-modify-write stopping hsclock
 * Used devm_platform_ioremap_resource for resource allocation
 * Removed unnecessary assert call from probe and remove.
 * wrap the line after the PTR_ERR() in probe()
 * Updated reset failure messages in probe
 * Fixed the typo arstc->prstc
 * Made hex constants to lower case.
RFC:
 * 
https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-22-biju.das...@bp.renesas.com/
 * 
https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-23-biju.das...@bp.renesas.com/

Biju Das (2):
  dt-bindings: display: bridge: Document RZ/G2L MIPI DSI TX bindings
  drm: rcar-du: Add RZ/G2L DSI driver

 .../bindings/display/bridge/renesas,dsi.yaml  | 182 +
 drivers/gpu/drm/rcar-du/Kconfig   |   8 +
 drivers/gpu/drm/rcar-du/Makefile  |   2 +
 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c  | 703 ++
 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h | 151 
 5 files changed, 1046 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
 create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
 create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h

-- 
2.25.1



[PATCH v6 1/2] dt-bindings: display: bridge: Document RZ/G2L MIPI DSI TX bindings

2022-08-29 Thread Biju Das
The RZ/G2L MIPI DSI TX is embedded in the Renesas RZ/G2L family SoC's. It
can operate in DSI mode, with up to four data lanes.

Signed-off-by: Biju Das 
Reviewed-by: Rob Herring 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Geert Uytterhoeven 
---
v5->v6:
 * No change.
v4->v5:
 * No change.
v3->v4:
 * No change.
v2->v3:
 * Added Rb tag from Geert and Laurent
 * Fixed the typo "Receive" -> "transmit"
 * Added accepible values for data-lanes
 * Sorted Header file in the example
 * Added SoC specific compaible along with generic one.
v1->v2:
 * Added full path for dsi-controller.yaml
 * Modeled DSI + D-PHY as single block and updated reg property
 * Fixed typo D_PHY->D-PHY
 * Updated description
 * Added interrupts and interrupt-names and updated the example 
RFC->v1:
 * Added a ref to dsi-controller.yaml.
RFC:-
 * 
https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-22-biju.das...@bp.renesas.com/
---
 .../bindings/display/bridge/renesas,dsi.yaml  | 182 ++
 1 file changed, 182 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
new file mode 100644
index ..131d5b63ec4f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/renesas,dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L MIPI DSI Encoder
+
+maintainers:
+  - Biju Das 
+
+description: |
+  This binding describes the MIPI DSI encoder embedded in the Renesas
+  RZ/G2L alike family of SoC's. The encoder can operate in DSI mode, with
+  up to four data lanes.
+
+allOf:
+  - $ref: /schemas/display/dsi-controller.yaml#
+
+properties:
+  compatible:
+items:
+  - enum:
+  - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
+  - const: renesas,rzg2l-mipi-dsi
+
+  reg:
+maxItems: 1
+
+  interrupts:
+items:
+  - description: Sequence operation channel 0 interrupt
+  - description: Sequence operation channel 1 interrupt
+  - description: Video-Input operation channel 1 interrupt
+  - description: DSI Packet Receive interrupt
+  - description: DSI Fatal Error interrupt
+  - description: DSI D-PHY PPI interrupt
+  - description: Debug interrupt
+
+  interrupt-names:
+items:
+  - const: seq0
+  - const: seq1
+  - const: vin1
+  - const: rcv
+  - const: ferr
+  - const: ppi
+  - const: debug
+
+  clocks:
+items:
+  - description: DSI D-PHY PLL multiplied clock
+  - description: DSI D-PHY system clock
+  - description: DSI AXI bus clock
+  - description: DSI Register access clock
+  - description: DSI Video clock
+  - description: DSI D-PHY Escape mode transmit clock
+
+  clock-names:
+items:
+  - const: pllclk
+  - const: sysclk
+  - const: aclk
+  - const: pclk
+  - const: vclk
+  - const: lpclk
+
+  resets:
+items:
+  - description: MIPI_DSI_CMN_RSTB
+  - description: MIPI_DSI_ARESET_N
+  - description: MIPI_DSI_PRESET_N
+
+  reset-names:
+items:
+  - const: rst
+  - const: arst
+  - const: prst
+
+  power-domains:
+maxItems: 1
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Parallel input port
+
+  port@1:
+$ref: /schemas/graph.yaml#/$defs/port-base
+unevaluatedProperties: false
+description: DSI output port
+
+properties:
+  endpoint:
+$ref: /schemas/media/video-interfaces.yaml#
+unevaluatedProperties: false
+
+properties:
+  data-lanes:
+description: array of physical DSI data lane indexes.
+minItems: 1
+items:
+  - const: 1
+  - const: 2
+  - const: 3
+  - const: 4
+
+required:
+  - data-lanes
+
+required:
+  - port@0
+  - port@1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-names
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - power-domains
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+dsi0: dsi@1085 {
+compatible = "renesas,r9a07g044-mipi-dsi", "renesas,rzg2l-mipi-dsi";
+reg = <0x1085 0x2>;
+interrupts = ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ;
+interrupt-names = "seq0", "seq1", "vin1", "rcv",
+  "ferr", "ppi", "debu

[PATCH v6 2/2] drm: rcar-du: Add RZ/G2L DSI driver

2022-08-29 Thread Biju Das
This driver supports the MIPI DSI encoder found in the RZ/G2L
SoC. It currently supports DSI video mode only.

Signed-off-by: Biju Das 
Acked-by: Sam Ravnborg 
---
v5->v6:
 * Updated commit description
 * Moved handling of arst and prst from rzg2l_mipi_dsi_startup->runtime
   PM suspend/resume handlers.
 * Max lane capability read at probe(), and enforced in
   rzg2l_mipi_dsi_host_attach()
 * Simplified vich1ppsetr setting.
 * Renamed hsclk_running_mode,hsclk_mode->is_clk_cont.
 * Fixed typo in probe error message(arst->rst).
 * Reordered DRM bridge initaization in probe()
 * Updated typo in e-mail address.
v4->v5:
 * Added Ack from Sam.
 * Added a trivial change, replaced rzg2l_mipi_dsi_parse_dt()
   with drm_of_get_data_lanes_count_ep() in probe.
v3->v4:
 * Updated error handling in rzg2l_mipi_dsi_startup() and 
rzg2l_mipi_dsi_atomic_enable()
v2->v3:
 * pass rzg2l_mipi_dsi pointer to {Link,Phy} register rd/wr function instead
   of the memory pointer
 * Fixed the comment in rzg2l_mipi_dsi_startup()
 * Removed unnecessary dbg message from rzg2l_mipi_dsi_start_video()
 * DRM bridge parameter initialization moved to probe
 * Replaced dev_dbg->dev_err in rzg2l_mipi_dsi_parse_dt()
 * Inserted the missing blank lane after return in probe()
 * Added missing MODULE_DEVICE_TABLE
 * Added include linux/bits.h in header file
 * Fixed various macros in header file.
 * Reorder the make file for DSI, so that it is no more dependent
   on RZ/G2L DU patch series.
v1->v2:
 * Rework based on dt-binding change (DSI + D-PHY) as single block
 * Replaced link_mmio and phy_mmio with mmio in struct rzg2l_mipi_dsi
 * Replaced rzg2l_mipi_phy_write with rzg2l_mipi_dsi_phy_write
   and rzg2l_mipi_dsi_link_write
 * Replaced rzg2l_mipi_phy_read->rzg2l_mipi_dsi_link_read
RFC->v1:
 * Added "depends on ARCH_RENESAS || COMPILE_TEST" on KCONFIG
   and dropped DRM as it is implied by DRM_BRIDGE
 * Used devm_reset_control_get_exclusive() for reset handle
 * Removed bool hsclkmode from struct rzg2l_mipi_dsi
 * Added error check for pm, using pm_runtime_resume_and_get() instead of
   pm_runtime_get_sync()
 * Added check for unsupported formats in rzg2l_mipi_dsi_host_attach()
 * Avoided read-modify-write stopping hsclock
 * Used devm_platform_ioremap_resource for resource allocation
 * Removed unnecessary assert call from probe and remove.
 * wrap the line after the PTR_ERR() in probe()
 * Updated reset failure messages in probe
 * Fixed the typo arstc->prstc
 * Made hex constants to lower case.
RFC:
 * 
https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-23-biju.das...@bp.renesas.com/
---
 drivers/gpu/drm/rcar-du/Kconfig   |   8 +
 drivers/gpu/drm/rcar-du/Makefile  |   2 +
 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c  | 703 ++
 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h | 151 
 4 files changed, 864 insertions(+)
 create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
 create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index c959e8c6be7d..58ffb8c2443b 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -51,6 +51,14 @@ config DRM_RCAR_MIPI_DSI
help
  Enable support for the R-Car Display Unit embedded MIPI DSI encoders.
 
+config DRM_RZG2L_MIPI_DSI
+   tristate "RZ/G2L MIPI DSI Encoder Support"
+   depends on DRM_BRIDGE && OF
+   depends on ARCH_RENESAS || COMPILE_TEST
+   select DRM_MIPI_DSI
+   help
+ Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
+
 config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support" if ARM
default y if ARM64
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 6f132325c8b7..b8f2c82651d9 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -14,3 +14,5 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
 obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
 obj-$(CONFIG_DRM_RCAR_LVDS)+= rcar_lvds.o
 obj-$(CONFIG_DRM_RCAR_MIPI_DSI)+= rcar_mipi_dsi.o
+
+obj-$(CONFIG_DRM_RZG2L_MIPI_DSI)   += rzg2l_mipi_dsi.o
diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c 
b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
new file mode 100644
index ..46a71e39e336
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
@@ -0,0 +1,703 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L MIPI DSI Encoder Driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rzg2l_mipi_dsi_regs.h"
+
+struct rzg2l_mipi_dsi {
+   struct device *dev;
+   void __iomem *mmio;
+
+   struct reset_contro

[PATCH v7] drm: Add initial ci/ subdirectory

2022-08-29 Thread Tomeu Vizoso
And use it to store expectations about what the DRM drivers are
supposed to pass in the IGT test suite.

Also include a configuration file that points to the out-of-tree CI
scripts.

By storing the test expectations along the code we can make sure both
stay in sync with each other, and so we can know when a code change
breaks those expectations.

This will allow all contributors to drm to reuse the infrastructure
already in gitlab.freedesktop.org to test the driver on several
generations of the hardware.

v2:
  - Fix names of result expectation files to match SoC
  - Don't execute tests that are going to skip on all boards

v3:
  - Remove tracking of dmesg output during test execution

v4:
  - Move up to drivers/gpu/drm
  - Add support for a bunch of other drivers
  - Explain how to incorporate fixes for CI from a
${TARGET_BRANCH}-external-fixes branch
  - Remove tests that pass from expected results file, to reduce the
size of in-tree files
  - Add docs about how to deal with outages in automated testing labs
  - Specify the exact SHA of the CI scripts to be used

v5:
  - Remove unneeded skips from Meson expectations file
  - Use a more advanced runner that detects flakes automatically
  - Use a more succint format for the expectations
  - Run many more tests (and use sharding to finish in time)
  - Use skip lists to avoid hanging machines
  - Add some build testing
  - Build IGT in each pipeline for faster uprevs
  - List failures in the GitLab UI

v6:
  - Rebase on top of latest drm-next
  - Lower priority of LAVA jobs to not impact Mesa CI as much
  - Update docs

v7:
  - Rebase on top of latest drm-next

Signed-off-by: Tomeu Vizoso 
Reviewed-by: Neil Armstrong 
Reviewed-by: Rob Clark 
---
 Documentation/gpu/automated_testing.rst   | 86 +++
 drivers/gpu/drm/ci/amdgpu-stoney-fails.txt| 19 
 drivers/gpu/drm/ci/amdgpu-stoney-flakes.txt   | 22 +
 drivers/gpu/drm/ci/amdgpu-stoney-skips.txt|  2 +
 drivers/gpu/drm/ci/gitlab-ci.yml  | 13 +++
 drivers/gpu/drm/ci/i915-amly-flakes.txt   | 32 +++
 drivers/gpu/drm/ci/i915-amly-skips.txt|  2 +
 drivers/gpu/drm/ci/i915-apl-fails.txt | 29 +++
 drivers/gpu/drm/ci/i915-apl-flakes.txt|  1 +
 drivers/gpu/drm/ci/i915-apl-skips.txt |  2 +
 drivers/gpu/drm/ci/i915-cml-flakes.txt| 36 
 drivers/gpu/drm/ci/i915-glk-flakes.txt| 40 +
 drivers/gpu/drm/ci/i915-glk-skips.txt |  2 +
 drivers/gpu/drm/ci/i915-kbl-fails.txt |  8 ++
 drivers/gpu/drm/ci/i915-kbl-flakes.txt| 24 ++
 drivers/gpu/drm/ci/i915-kbl-skips.txt |  2 +
 drivers/gpu/drm/ci/i915-tgl-fails.txt | 19 
 drivers/gpu/drm/ci/i915-tgl-flakes.txt|  6 ++
 drivers/gpu/drm/ci/i915-tgl-skips.txt |  8 ++
 drivers/gpu/drm/ci/i915-whl-fails.txt | 30 +++
 drivers/gpu/drm/ci/i915-whl-flakes.txt|  1 +
 drivers/gpu/drm/ci/mediatek-mt8173-fails.txt  | 29 +++
 drivers/gpu/drm/ci/mediatek-mt8183-fails.txt  | 10 +++
 drivers/gpu/drm/ci/mediatek-mt8183-flakes.txt | 14 +++
 drivers/gpu/drm/ci/meson-g12b-fails.txt   |  5 ++
 drivers/gpu/drm/ci/meson-g12b-flakes.txt  |  4 +
 drivers/gpu/drm/ci/msm-apq8016-fails.txt  | 15 
 drivers/gpu/drm/ci/msm-apq8016-flakes.txt |  4 +
 drivers/gpu/drm/ci/msm-apq8096-fails.txt  |  2 +
 drivers/gpu/drm/ci/msm-apq8096-flakes.txt |  4 +
 drivers/gpu/drm/ci/msm-apq8096-skips.txt  |  2 +
 drivers/gpu/drm/ci/msm-sc7180-fails.txt   | 21 +
 drivers/gpu/drm/ci/msm-sc7180-flakes.txt  | 14 +++
 drivers/gpu/drm/ci/msm-sc7180-skips.txt   | 23 +
 drivers/gpu/drm/ci/msm-sdm845-fails.txt   | 44 ++
 drivers/gpu/drm/ci/msm-sdm845-flakes.txt  | 14 +++
 drivers/gpu/drm/ci/msm-sdm845-skips.txt   |  2 +
 drivers/gpu/drm/ci/rockchip-rk3288-fails.txt  | 47 ++
 drivers/gpu/drm/ci/rockchip-rk3288-flakes.txt |  9 ++
 drivers/gpu/drm/ci/rockchip-rk3288-skips.txt  | 46 ++
 drivers/gpu/drm/ci/rockchip-rk3399-fails.txt  | 44 ++
 drivers/gpu/drm/ci/rockchip-rk3399-flakes.txt | 19 
 drivers/gpu/drm/ci/rockchip-rk3399-skips.txt  |  5 ++
 drivers/gpu/drm/ci/virtio_gpu-none-fails.txt  | 38 
 drivers/gpu/drm/ci/virtio_gpu-none-flakes.txt |  0
 drivers/gpu/drm/ci/virtio_gpu-none-skips.txt  |  6 ++
 46 files changed, 805 insertions(+)
 create mode 100644 Documentation/gpu/automated_testing.rst
 create mode 100644 drivers/gpu/drm/ci/amdgpu-stoney-fails.txt
 create mode 100644 drivers/gpu/drm/ci/amdgpu-stoney-flakes.txt
 create mode 100644 drivers/gpu/drm/ci/amdgpu-stoney-skips.txt
 create mode 100644 drivers/gpu/drm/ci/gitlab-ci.yml
 create mode 100644 drivers/gpu/drm/ci/i915-amly-flakes.txt
 create mode 100644 drivers/gpu/drm/ci/i915-amly-skips.txt
 create mode 100644 drivers/gpu/drm/ci/i915-apl-fails.txt
 create mode 100644 drivers/gpu/drm/ci/i915-apl-flakes.txt
 create mode 100644 drivers/gpu/drm/ci/i915-apl-skips.txt
 creat

Re: [PATCH v4,1/2] soc: mediatek: Add mmsys func to adapt to dpi output for MT8186

2022-08-29 Thread AngeloGioacchino Del Regno

Il 29/08/22 05:21, xinlei@mediatek.com ha scritto:

From: Xinlei Lee 

Add mmsys func to manipulate dpi output format config for MT8186.

Co-developed-by: Jitao Shi 
Signed-off-by: Jitao Shi 
Signed-off-by: Xinlei Lee 
Reviewed-by: Nícolas F. R. A. Prado 
---
  drivers/soc/mediatek/mt8186-mmsys.h| 1 +
  drivers/soc/mediatek/mtk-mmsys.c   | 8 
  include/linux/soc/mediatek/mtk-mmsys.h | 3 +++
  3 files changed, 12 insertions(+)

diff --git a/drivers/soc/mediatek/mt8186-mmsys.h 
b/drivers/soc/mediatek/mt8186-mmsys.h
index eb1ad9c37a9c..6eca3445bea3 100644
--- a/drivers/soc/mediatek/mt8186-mmsys.h
+++ b/drivers/soc/mediatek/mt8186-mmsys.h
@@ -3,6 +3,7 @@
  #ifndef __SOC_MEDIATEK_MT8186_MMSYS_H
  #define __SOC_MEDIATEK_MT8186_MMSYS_H
  
+#define MT8186_DPI_OUTPUT_FORMAT		0x400


For readability, can we please rename this definition to

MT8186_MMSYS_DPI_OUTPUT_FORMAT

Thanks,
Angelo



Re: [PATCH v4,2/2] drm: mediatek: Adjust the dpi output format to MT8186

2022-08-29 Thread AngeloGioacchino Del Regno

Il 29/08/22 05:21, xinlei@mediatek.com ha scritto:

From: Xinlei Lee 

Dpi output needs to adjust the output format to dual edge for MT8186.

Co-developed-by: Jitao Shi 
Signed-off-by: Jitao Shi 
Signed-off-by: Xinlei Lee 

---
  drivers/gpu/drm/mediatek/mtk_dpi.c  | 32 +
  drivers/gpu/drm/mediatek/mtk_dpi_regs.h |  5 
  drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  2 ++
  3 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c 
b/drivers/gpu/drm/mediatek/mtk_dpi.c
index fb0b79704636..c23ef7deef26 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -14,6 +14,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  
  #include 

@@ -28,6 +29,7 @@
  #include "mtk_disp_drv.h"
  #include "mtk_dpi_regs.h"
  #include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_drv.h"
  
  enum mtk_dpi_out_bit_num {

MTK_DPI_OUT_BIT_NUM_8BITS,
@@ -80,6 +82,7 @@ struct mtk_dpi {
struct pinctrl_state *pins_dpi;
u32 output_fmt;
int refcount;
+   struct device *mmsys_dev;
  };
  
  static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b)

@@ -133,6 +136,8 @@ struct mtk_dpi_yc_limit {
   * @yuv422_en_bit: Enable bit of yuv422.
   * @csc_enable_bit: Enable bit of CSC.
   * @pixels_per_iter: Quantity of transferred pixels per iteration.
+ * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be
+ *set in MMSYS.


 * @edge_cfg_in_mmsys: Edge configuration for DPI output has to be set in MMSYS.

fits in one line and it's more immediate to read.

After which...

Reviewed-by: AngeloGioacchino Del Regno 




[PATCH 0/4] Add DP MST DSC support to i915

2022-08-29 Thread Stanislav Lisovskiy
Currently we have only DSC support for DP SST.

Stanislav Lisovskiy (4):
  drm: Add missing DP DSC extended capability definitions.
  drm/i915: Fix intel_dp_mst_compute_link_config
  drm/i915: Add DSC support to MST path
  drm/i915: Extract drm_dp_atomic_find_vcpi_slots cycle to separate
function

 drivers/gpu/drm/i915/display/intel_dp.c |  73 +++
 drivers/gpu/drm/i915/display/intel_dp.h |  17 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 205 ++--
 include/drm/display/drm_dp.h|  10 +-
 4 files changed, 246 insertions(+), 59 deletions(-)

-- 
2.24.1.485.gad05a3d8e5



[PATCH 3/4] drm/i915: Add DSC support to MST path

2022-08-29 Thread Stanislav Lisovskiy
Whenever we are not able to get enough timeslots
for required PBN, let's try to allocate those
using DSC, just same way as we do for SST.

v2: Removed intel_dp_mst_dsc_compute_config and refactored
intel_dp_dsc_compute_config to support timeslots as a
parameter(Ville Syrjälä)

v3: - Rebased
- Added a debug to see that we at least try reserving
  VCPI slots using DSC, because currently its not visible
  from the logs, thus making debugging more tricky.
- Moved timeslots to numerator, where it should be.

v4: - Call drm_dp_mst_atomic_check already during link
  config computation, because we need to know already
  by this moment if uncompressed amount of VCPI slots
  needed can fit, otherwise we need to use DSC.
  (thanks to Vinod Govindapillai for pointing this out)

v5: - Put pipe_config->bigjoiner_pipes back to original
  condition in intel_dp_dsc_compute_config
  (don't remember when I lost it)

Signed-off-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp.c |  73 -
 drivers/gpu/drm/i915/display/intel_dp.h |  17 +++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 157 
 3 files changed, 205 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 8d1559323412..044b395fea67 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -116,7 +116,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
 }
 
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
-static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
 
 /* Is link rate UHBR and thus 128b/132b? */
 bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
@@ -687,11 +686,12 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915)
return 6144 * 8;
 }
 
-static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
-  u32 link_clock, u32 lane_count,
-  u32 mode_clock, u32 mode_hdisplay,
-  bool bigjoiner,
-  u32 pipe_bpp)
+u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
+   u32 link_clock, u32 lane_count,
+   u32 mode_clock, u32 mode_hdisplay,
+   bool bigjoiner,
+   u32 pipe_bpp,
+   u32 timeslots)
 {
u32 bits_per_pixel, max_bpp_small_joiner_ram;
int i;
@@ -702,8 +702,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct 
drm_i915_private *i915,
 * for SST -> TimeSlotsPerMTP is 1,
 * for MST -> TimeSlotsPerMTP has to be calculated
 */
-   bits_per_pixel = (link_clock * lane_count * 8) /
+   bits_per_pixel = (link_clock * lane_count * 8) * timeslots /
 intel_dp_mode_to_fec_clock(mode_clock);
+   drm_dbg_kms(&i915->drm, "Max link bpp: %u\n", bits_per_pixel);
 
/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) /
@@ -752,9 +753,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct 
drm_i915_private *i915,
return bits_per_pixel << 4;
 }
 
-static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
-  int mode_clock, int mode_hdisplay,
-  bool bigjoiner)
+u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+   int mode_clock, int mode_hdisplay,
+   bool bigjoiner)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 min_slice_count, i;
@@ -961,8 +962,8 @@ intel_dp_mode_valid_downstream(struct intel_connector 
*connector,
return MODE_OK;
 }
 
-static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
-   int hdisplay, int clock)
+bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
+int hdisplay, int clock)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 
@@ -1049,7 +1050,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
target_clock,
mode->hdisplay,
bigjoiner,
-   pipe_bpp) >> 4;
+   pipe_bpp, 1) >> 4;
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
 target_clock,
@@ -1354,7 +1355,7 @@ intel_dp_compute_link_config_wide(struct intel_dp 

[PATCH 1/4] drm: Add missing DP DSC extended capability definitions.

2022-08-29 Thread Stanislav Lisovskiy
Adding DP DSC register definitions, we might need for further
DSC implementation, supporting MST and DP branch pass-through mode.

v2: - Fixed checkpatch comment warning
v3: - Removed function which is not yet used(Jani Nikula)

Reviewed-by: Vinod Govindapillai 

Signed-off-by: Stanislav Lisovskiy 
---
 include/drm/display/drm_dp.h | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 9e3aff7e68bb..0d05e3172f96 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -239,6 +239,9 @@
 
 #define DP_DSC_SUPPORT  0x060   /* DP 1.4 */
 # define DP_DSC_DECOMPRESSION_IS_SUPPORTED  (1 << 0)
+# define DP_DSC_PASS_THROUGH_IS_SUPPORTED   (1 << 1)
+# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_COMP_TO_COMP(1 << 2)
+# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_UNCOMP_TO_COMP  (1 << 3)
 
 #define DP_DSC_REV  0x061
 # define DP_DSC_MAJOR_MASK  (0xf << 0)
@@ -277,12 +280,15 @@
 
 #define DP_DSC_BLK_PREDICTION_SUPPORT   0x066
 # define DP_DSC_BLK_PREDICTION_IS_SUPPORTED (1 << 0)
+# define DP_DSC_RGB_COLOR_CONV_BYPASS_SUPPORT (1 << 1)
 
 #define DP_DSC_MAX_BITS_PER_PIXEL_LOW   0x067   /* eDP 1.4 */
 
 #define DP_DSC_MAX_BITS_PER_PIXEL_HI0x068   /* eDP 1.4 */
 # define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK  (0x3 << 0)
 # define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8
+# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK  0x06
+# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY  0x08
 
 #define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069
 # define DP_DSC_RGB (1 << 0)
@@ -344,11 +350,13 @@
 # define DP_DSC_24_PER_DP_DSC_SINK  (1 << 2)
 
 #define DP_DSC_BITS_PER_PIXEL_INC   0x06F
+# define DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK 0x1f
+# define DP_DSC_RGB_YCbCr420_MAX_BPP_DELTA_MASK 0xe0
 # define DP_DSC_BITS_PER_PIXEL_1_16 0x0
 # define DP_DSC_BITS_PER_PIXEL_1_8  0x1
 # define DP_DSC_BITS_PER_PIXEL_1_4  0x2
 # define DP_DSC_BITS_PER_PIXEL_1_2  0x3
-# define DP_DSC_BITS_PER_PIXEL_10x4
+# define DP_DSC_BITS_PER_PIXEL_1_1  0x4
 
 #define DP_PSR_SUPPORT  0x070   /* XXX 1.2? */
 # define DP_PSR_IS_SUPPORTED1
-- 
2.24.1.485.gad05a3d8e5



[PATCH 2/4] drm/i915: Fix intel_dp_mst_compute_link_config

2022-08-29 Thread Stanislav Lisovskiy
We currently always exit that bpp loop because drm_dp_atomic_find_vcpi_slots
doesn't care if we actually can fit those or not.
I think that wasn't the initial intention here, especially when
we keep trying with lower bpps, we are supposed to keep trying
until we actually find some _working_ configuration, which isn't the
case here.
So added that drm_dp_mst_check here, so that we can make sure
that try all the bpps before we fail.

Signed-off-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 13abe2b2170e..c4f92edbdd08 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -60,6 +60,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
&crtc_state->hw.adjusted_mode;
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL;
+   int ret = 0;
 
mst_state = drm_atomic_get_mst_topology_state(state, 
&intel_dp->mst_mgr);
if (IS_ERR(mst_state))
@@ -85,10 +86,21 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
  connector->port, 
crtc_state->pbn);
if (slots == -EDEADLK)
return slots;
-   if (slots >= 0)
-   break;
+   if (slots >= 0) {
+   ret = drm_dp_mst_atomic_check(state);
+   /*
+* If we got slots >= 0 and we can fit those based on 
check
+* then we can exit the loop. Otherwise keep trying.
+*/
+   if (!ret)
+   break;
+   }
}
 
+   /* Despite slots are non-zero, we still failed the atomic check */
+   if (ret && slots >= 0)
+   slots = ret;
+
if (slots < 0) {
drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",
slots);
-- 
2.24.1.485.gad05a3d8e5



[PATCH 4/4] drm/i915: Extract drm_dp_atomic_find_vcpi_slots cycle to separate function

2022-08-29 Thread Stanislav Lisovskiy
We are using almost same code to loop through bpps while calling
drm_dp_atomic_find_vcpi_slots - lets remove this duplication by
introducing a new function intel_dp_mst_find_vcpi_slots_for_bpp

Signed-off-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 88 +++--
 1 file changed, 46 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 94d7e7f84c51..2a524816dbfd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -44,10 +44,14 @@
 #include "intel_hotplug.h"
 #include "skl_scaler.h"
 
-static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
-   struct intel_crtc_state *crtc_state,
-   struct drm_connector_state 
*conn_state,
-   struct link_config_limits *limits)
+static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
+   struct intel_crtc_state 
*crtc_state,
+   int max_bpp,
+   int min_bpp,
+   struct link_config_limits 
*limits,
+   struct drm_connector_state 
*conn_state,
+   int step,
+   bool dsc)
 {
struct drm_atomic_state *state = crtc_state->uapi.state;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
@@ -58,7 +62,6 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
-   bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL;
int ret = 0;
 
@@ -71,19 +74,21 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
 
// TODO: Handle pbn_div changes by adding a new MST helper
if (!mst_state->pbn_div) {
-   mst_state->pbn_div = 
drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
- limits->max_rate,
- 
limits->max_lane_count);
+   mst_state->pbn_div = !dsc ? 
drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
+
crtc_state->port_clock,
+
crtc_state->lane_count) : 0;
}
 
-   for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
+   for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp,
-  false);
+  dsc ? bpp << 4 : 
crtc_state->pipe_bpp,
+  dsc);
+
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
- connector->port, 
crtc_state->pbn);
+ connector->port,
+ crtc_state->pbn);
if (slots == -EDEADLK)
return slots;
if (slots >= 0) {
@@ -101,11 +106,32 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
if (ret && slots >= 0)
slots = ret;
 
-   if (slots < 0) {
+   if (slots < 0)
drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",
slots);
+
+   return slots;
+}
+
+
+static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state 
*conn_state,
+   struct link_config_limits *limits)
+{
+   const struct drm_display_mode *adjusted_mode =
+   &crtc_state->hw.adjusted_mode;
+   struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
+   struct intel_dp *intel_dp = &intel_mst->primary->dp;
+   bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
DP_DPCD_QUIRK_CONSTANT_N);
+   int slots = -EINVAL;
+
+   slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, 
limits->max_bpp,
+

[PATCH v3] drm/ast: add dmabuf/prime buffer sharing support

2022-08-29 Thread oushixiong
This patch adds ast specific codes for DRM prime feature, this is to
allow for offloading of rending in one direction and outputs in other.

This patch is designed to solve the problem that the AST is not displayed
when the server plug in a discrete  graphics card at the same time.
We call the dirty callback function to copy the rendering results of the
discrete graphics card to the ast side by dma-buf.

v1->v2:
  - Fix the comment.
v2->v3:
  - we remove the gem_prime_import_sg_table callback and use the
gem_prime_import callback, because it just map and access the buffer
with the CPU. and do not to pin the buffer.

Signed-off-by: oushixiong 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/ast_drv.c  |  27 +++
 drivers/gpu/drm/ast/ast_mode.c | 125 -
 2 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 7465c4f0156a..fd3c4bad2eb4 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -28,6 +28,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -50,6 +51,29 @@ module_param_named(modeset, ast_modeset, int, 0400);
 
 DEFINE_DRM_GEM_FOPS(ast_fops);
 
+static struct drm_gem_object *ast_gem_prime_import(struct drm_device *dev,
+   struct dma_buf *dma_buf)
+{
+   struct drm_gem_vram_object *gbo;
+
+   gbo = drm_gem_vram_of_gem(dma_buf->priv);
+   if (gbo->bo.base.dev == dev) {
+   /*
+* Importing dmabuf exported from out own gem increases
+* refcount on gem itself instead of f_count of dmabuf.
+*/
+   drm_gem_object_get(&gbo->bo.base);
+   return &gbo->bo.base;
+   }
+
+   gbo = drm_gem_vram_create(dev, dma_buf->size, 0);
+   if (IS_ERR(gbo))
+   return NULL;
+
+   get_dma_buf(dma_buf);
+   return &gbo->bo.base;
+}
+
 static const struct drm_driver ast_driver = {
.driver_features = DRIVER_ATOMIC |
   DRIVER_GEM |
@@ -63,6 +87,9 @@ static const struct drm_driver ast_driver = {
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
 
+   .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+   .gem_prime_import = ast_gem_prime_import,
+
DRM_GEM_VRAM_DRIVER
 };
 
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 45b56b39ad47..65a4342c5622 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -48,6 +48,8 @@
 #include "ast_drv.h"
 #include "ast_tables.h"
 
+MODULE_IMPORT_NS(DMA_BUF);
+
 static inline void ast_load_palette_index(struct ast_private *ast,
 u8 index, u8 red, u8 green,
 u8 blue)
@@ -1535,8 +1537,129 @@ static const struct drm_mode_config_helper_funcs 
ast_mode_config_helper_funcs =
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+static int ast_handle_damage(struct drm_framebuffer *fb, int x, int y,
+   int width, int height)
+{
+   struct drm_gem_vram_object *dst_bo = NULL;
+   void *dst = NULL;
+   int ret = 0, i;
+   unsigned long offset = 0;
+   bool unmap = false;
+   unsigned int bytesPerPixel;
+   struct iosys_map map;
+   struct iosys_map dmabuf_map;
+
+   bytesPerPixel = fb->format->cpp[0];
+
+   if (!fb->obj[0]->dma_buf)
+   return -EINVAL;
+
+   if (!fb->obj[0]->dma_buf->vmap_ptr.vaddr) {
+   ret = dma_buf_vmap(fb->obj[0]->dma_buf, &dmabuf_map);
+   if (ret)
+   return ret;
+   } else
+   dmabuf_map.vaddr = fb->obj[0]->dma_buf->vmap_ptr.vaddr;
+
+   dst_bo = drm_gem_vram_of_gem(fb->obj[0]);
+
+   ret = drm_gem_vram_pin(dst_bo, 0);
+   if (ret) {
+   DRM_ERROR("ast_bo_pin failed\n");
+   return ret;
+   }
+
+   if (!dst_bo->map.vaddr) {
+   ret = drm_gem_vram_vmap(dst_bo, &map);
+   if (ret) {
+   drm_gem_vram_unpin(dst_bo);
+   DRM_ERROR("failed to vmap fbcon\n");
+   return ret;
+   }
+   unmap = true;
+   }
+   dst = dst_bo->map.vaddr;
+
+   for (i = y; i < y + height; i++) {
+   offset = i * fb->pitches[0] + (x * bytesPerPixel);
+   memcpy_toio(dst + offset, dmabuf_map.vaddr + offset,
+   width * bytesPerPixel);
+   }
+
+   if (unmap)
+   drm_gem_vram_vunmap(dst_bo, &map);
+
+   drm_gem_vram_unpin(dst_bo);
+
+   return 0;
+}
+
+
+static int ast_user_framebuffer_dirty(struct drm_framebuffer *fb,
+   struct drm_file *file,
+   unsigned int flags,
+   unsigned int color,
+ 

Re: [PATCH v5 17/31] ACPI: video: Add Nvidia WMI EC brightness control detection (v3)

2022-08-29 Thread Hans de Goede
Hi,

On 8/26/22 00:21, Daniel Dadap wrote:
> On 8/25/22 9:37 AM, Hans de Goede wrote:
>> On some new laptop designs a new Nvidia specific WMI interface is present
>> which gives info about panel brightness control and may allow controlling
>> the brightness through this interface when the embedded controller is used
>> for brightness control.
>>
>> When this WMI interface is present and indicates that the EC is used,
>> then this interface should be used for brightness control.
>>
>> Changes in v2:
>> - Use the new shared nvidia-wmi-ec-backlight.h header for the
>>    WMI firmware API definitions
>> - ACPI_VIDEO can now be enabled on non X86 too,
>>    adjust the Kconfig changes to match this.
>>
>> Changes in v3:
>> - Use WMI_BRIGHTNESS_GUID define
>>
>> Acked-by: Rafael J. Wysocki 
>> Signed-off-by: Hans de Goede 
>> ---
>>   drivers/acpi/Kconfig   |  1 +
>>   drivers/acpi/video_detect.c    | 37 ++
>>   drivers/gpu/drm/gma500/Kconfig |  2 ++
>>   drivers/gpu/drm/i915/Kconfig   |  2 ++
>>   include/acpi/video.h   |  1 +
>>   5 files changed, 43 insertions(+)
>>
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index 7802d8846a8d..44ad4b6bd234 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -212,6 +212,7 @@ config ACPI_VIDEO
>>   tristate "Video"
>>   depends on BACKLIGHT_CLASS_DEVICE
>>   depends on INPUT
>> +    depends on ACPI_WMI || !X86
>>   select THERMAL
>>   help
>>     This driver implements the ACPI Extensions For Display Adapters
>> diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
>> index cc9d0d91e268..4dc7fb865083 100644
>> --- a/drivers/acpi/video_detect.c
>> +++ b/drivers/acpi/video_detect.c
>> @@ -32,6 +32,7 @@
>>   #include 
>>   #include 
>>   #include 
>> +#include 
>>   #include 
>>   #include 
>>   #include 
>> @@ -75,6 +76,36 @@ find_video(acpi_handle handle, u32 lvl, void *context, 
>> void **rv)
>>   return AE_OK;
>>   }
>>   +/* This depends on ACPI_WMI which is X86 only */
>> +#ifdef CONFIG_X86
> 
> 
> This could probably also provide the { return false; } stub which you have 
> for non-x86 if the kernel is built without nvidia-wmi-ec-backight, e.g.:
> 
> #if defined(CONFIG_X86) && (defined(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) || 
> defined(CONFIG_NVIDIA_WMI_EC_BACKLIGHT_MODULE))
> 
> Although I suppose that would break things if somebody has a kernel that 
> originally had NVIDIA_WMI_EC_BACKLIGHT=n in Kconfig, and then builds the 
> nvidia-wmi-ec-backlight driver out-of-tree later. I don't know whether that's 
> intended to be a supported use case, so I guess it is fine either way.

The video-detect code is about detecting what interface should be used.
So far it does this independently of the driver implementing that interface
actually being enabled or not.

If someone has a system which needs the nvidia-wmi-ec-backlight driver,
but it is disabled then they / their distro should enable that driver,
rather then trying to fallback on e.g. acpi_video.

Taking which drivers are enabled into account would both make
the code more complicated and would also explode the test matrix.

All of this is already somewhat fragile, so lets not make it
extra complicated :)

Regards,

Hans



> 
> 
>> +static bool nvidia_wmi_ec_supported(void)
>> +{
>> +    struct wmi_brightness_args args = {
>> +    .mode = WMI_BRIGHTNESS_MODE_GET,
>> +    .val = 0,
>> +    .ret = 0,
>> +    };
>> +    struct acpi_buffer buf = { (acpi_size)sizeof(args), &args };
>> +    acpi_status status;
>> +
>> +    status = wmi_evaluate_method(WMI_BRIGHTNESS_GUID, 0,
>> + WMI_BRIGHTNESS_METHOD_SOURCE, &buf, &buf);
>> +    if (ACPI_FAILURE(status))
>> +    return false;
>> +
>> +    /*
>> + * If brightness is handled by the EC then nvidia-wmi-ec-backlight
>> + * should be used, else the GPU driver(s) should be used.
>> + */
>> +    return args.ret == WMI_BRIGHTNESS_SOURCE_EC;
>> +}
>> +#else
>> +static bool nvidia_wmi_ec_supported(void)
>> +{
>> +    return false;
>> +}
>> +#endif
>> +
>>   /* Force to use vendor driver when the ACPI device is known to be
>>    * buggy */
>>   static int video_detect_force_vendor(const struct dmi_system_id *d)
>> @@ -541,6 +572,7 @@ static const struct dmi_system_id 
>> video_detect_dmi_table[] = {
>>   static enum acpi_backlight_type __acpi_video_get_backlight_type(bool 
>> native)
>>   {
>>   static DEFINE_MUTEX(init_mutex);
>> +    static bool nvidia_wmi_ec_present;
>>   static bool native_available;
>>   static bool init_done;
>>   static long video_caps;
>> @@ -553,6 +585,7 @@ static enum acpi_backlight_type 
>> __acpi_video_get_backlight_type(bool native)
>>   acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
>>   ACPI_UINT32_MAX, find_video, NULL,
>>   &video_caps, NULL);
>> +    nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
>> 

Aw: [PATCH 1/2] drm/etnaviv: add HWDB entry for GC7000 r6203

2022-08-29 Thread Stefan Eschenbacher
Product_id, customer_id and eco_id should not be zero. The different versions 
of model 0x7000, revision 0x6203 can differ in stream_count, minor_feature5 and 
minor_features7.
 
{
   .model = 0x7000,
   .revision = 0x6203,
   .product_id = 0x70003,
   .customer_id = 0x4,
   .eco_id = 0,
   .stream_count = 16,
   .register_max = 64,
   .thread_count = 512,
   .shader_core_count = 2,
   .vertex_cache_size = 16,
   .vertex_output_buffer_size = 1024,
   .pixel_pipes = 1,
   .instruction_count = 512,
   .num_constants = 320,
   .buffer_size = 0,
   .varyings_count = 16,
   .features = 0xe0287c8d,
   .minor_features0 = 0xc1799eff,
   .minor_features1 = 0xfefbfad9,
   .minor_features2 = 0xeb9d4fbf,
   .minor_features3 = 0xedfffced,
   .minor_features4 = 0xdb0dafc7,
   .minor_features5 = 0x3b5ac333,
   .minor_features6 = 0xfcce6000,
   .minor_features7 = 0xfffbfa6f,
   .minor_features8 = 0x00e10ef3,
   .minor_features9 = 0x00c8003c,
   .minor_features10 = 0x4040,
   .minor_features11 = 0x0024,
},
{
   .model = 0x7000,
   .revision = 0x6203,
   .product_id = 0x7000f,
   .customer_id = 0x60,
   .eco_id = 0,
   .stream_count = 8,
   .register_max = 64,
   .thread_count = 512,
   .shader_core_count = 2,
   .vertex_cache_size = 16,
   .vertex_output_buffer_size = 1024,
   .pixel_pipes = 1,
   .instruction_count = 512,
   .num_constants = 320,
   .buffer_size = 0,
   .varyings_count = 16,
   .features = 0xe0287c8d,
.minor_features0 = 0xc1799eff,
   .minor_features1 = 0xfefbfad9,
   .minor_features2 = 0xeb9d4fbf,
   .minor_features3 = 0xedfffced,
   .minor_features4 = 0xdb0dafc7,
   .minor_features5 = 0x7b5ac333,
   .minor_features6 = 0xfcce6000,
   .minor_features7 = 0x1bfbfa6f,
   .minor_features8 = 0x00e10ef0,
   .minor_features9 = 0x00c8003c,
   .minor_features10 = 0x4040,
   .minor_features11 = 0x0024,
},

Take a look in the stm32 hwdb file.

[PATCH v2 11/11] drm/i915: Infer vrefresh range for eDP if the EDID omits it

2022-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

A bunch of machines seem to have eDP panels where the EDID
indicates continuous frequency support but fails to actually
include the range descirptor. This violates the EDID 1.4
spec, but looks like the Windows driver just hacks around
this by just assuming that the panel supports a continuous
refresh rate range that covers all EDID reported modes.

Do the same so that we get VRR support on these machines.

v2: connector->edid may be an error pointer (Jani)

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6323
Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 8d1559323412..df2b2064ce50 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5207,6 +5207,49 @@ intel_edp_add_properties(struct intel_dp *intel_dp)
   fixed_mode->vdisplay);
 }
 
+/*
+ * Some VRR eDP panels violate the EDID spec and neglect
+ * to include the monitor range descriptor in the EDID.
+ * Cook up the VRR refresh rate limits based on the modes
+ * reported by the panel.
+ */
+static void
+intel_edp_infer_vrr_range(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct drm_display_info *info = &connector->base.display_info;
+   const struct edid *edid = connector->edid;
+   const struct drm_display_mode *mode;
+
+   if (!HAS_VRR(i915))
+   return;
+
+   if (IS_ERR_OR_NULL(edid) || edid->revision < 4 ||
+   !(edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) ||
+   info->vrr_range.min_vfreq || info->vrr_range.max_vfreq)
+   return;
+
+   if (list_empty(&connector->base.probed_modes))
+   return;
+
+   info->vrr_range.min_vfreq = ~0;
+   info->vrr_range.max_vfreq = 0;
+
+   list_for_each_entry(mode, &connector->base.probed_modes, head) {
+   int vrefresh = drm_mode_vrefresh(mode);
+
+   info->vrr_range.min_vfreq = min_t(int, vrefresh,
+ info->vrr_range.min_vfreq);
+   info->vrr_range.max_vfreq = max_t(int, vrefresh,
+ info->vrr_range.max_vfreq);
+   }
+
+   drm_dbg_kms(&i915->drm,
+   "[CONNECTOR:%d:%s] does not report refresh rate range, 
assuming: %d Hz - %d Hz\n",
+   connector->base.base.id, connector->base.name,
+   info->vrr_range.min_vfreq, info->vrr_range.max_vfreq);
+}
+
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 struct intel_connector *intel_connector)
 {
@@ -5271,6 +5314,8 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
}
intel_connector->edid = edid;
 
+   intel_edp_infer_vrr_range(intel_connector);
+
intel_bios_init_panel(dev_priv, &intel_connector->panel,
  encoder->devdata, IS_ERR(edid) ? NULL : edid);
 
-- 
2.35.1



[PATCH] drm/i915/ttm: Abort suspend on i915_ttm_backup failure

2022-08-29 Thread Nirmoy Das
On system suspend when system memory is low then i915_gem_obj_copy_ttm()
could fail trying to backup a lmem obj. GEM_WARN_ON() is not enough,
suspend shouldn't continue if i915_ttm_backup() throws an error.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6529
Suggested-by: Chris P Wilson 
Signed-off-by: Nirmoy Das 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
index 9aad84059d56..6f5d5c0909b4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
@@ -79,7 +79,12 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region 
*apply,
goto out_no_populate;
 
err = i915_gem_obj_copy_ttm(backup, obj, pm_apply->allow_gpu, false);
-   GEM_WARN_ON(err);
+   if (err) {
+   drm_err(&i915->drm,
+   "Unable to copy from device to system memory, err:%d\n",
+   err);
+   goto out_no_populate;
+   }
ttm_bo_wait_ctx(backup_bo, &ctx);
 
obj->ttm.backup = backup;
-- 
2.35.1



[PATCH linux-next] drm/amd/display: remove redundant vertical_line_start variable

2022-08-29 Thread cgel . zte
From: Jinpeng Cui 

Return value from expression directly instead of
taking this in another redundant variable.

Reported-by: Zeal Robot 
Signed-off-by: Jinpeng Cui 
---
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 37246e965457..8f4f1ea447a7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -3741,7 +3741,6 @@ int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx 
*pipe_ctx)
int vesa_sync_start;
int asic_blank_end;
int interlace_factor;
-   int vertical_line_start;
 
patched_crtc_timing = *dc_crtc_timing;
apply_front_porch_workaround(&patched_crtc_timing);
@@ -3757,10 +3756,8 @@ int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx 
*pipe_ctx)
patched_crtc_timing.v_border_top)
* interlace_factor;
 
-   vertical_line_start = asic_blank_end -
+   return asic_blank_end -
pipe_ctx->pipe_dlg_param.vstartup_start + 1;
-
-   return vertical_line_start;
 }
 
 void dcn10_calc_vupdate_position(
-- 
2.25.1



Re: [PATCH v1 23/35] drm/vc4: vec: Convert to the new TV mode property

2022-08-29 Thread Maxime Ripard
Hi Noralf,

On Thu, Aug 25, 2022 at 03:14:01PM +0200, Noralf Trønnes wrote:
> Den 24.08.2022 17.26, skrev Maxime Ripard:
> > On Sat, Aug 20, 2022 at 07:22:48PM +0200, Noralf Trønnes wrote:
> >> Den 29.07.2022 18.35, skrev Maxime Ripard:
> >>> Now that the core can deal fine with analog TV modes, let's convert the 
> >>> vc4
> >>> VEC driver to leverage those new features.
> >>>
> >>> We've added some backward compatibility to support the old TV mode 
> >>> property
> >>> and translate it into the new TV norm property.
> >>>
> >>> Signed-off-by: Maxime Ripard 
> >>>
> >>> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> >>
> >>>  static int vc4_vec_connector_get_modes(struct drm_connector *connector)
> >>>  {
> >>> - struct drm_connector_state *state = connector->state;
> >>>   struct drm_display_mode *mode;
> >>>  
> >>> - mode = drm_mode_duplicate(connector->dev,
> >>> -   vc4_vec_tv_modes[state->tv.mode].mode);
> >>> + mode = drm_mode_duplicate(connector->dev, &drm_mode_480i);
> >>> + if (!mode) {
> >>> + DRM_ERROR("Failed to create a new display mode\n");
> >>> + return -ENOMEM;
> >>> + }
> >>> +
> >>> + drm_mode_probed_add(connector, mode);
> >>> +
> >>> + mode = drm_mode_duplicate(connector->dev, &drm_mode_576i);
> >>
> >> Maybe the mode that matches tv.norm should be marked as preferred so
> >> userspace knows which one to pick?
> > 
> > I'm not sure how realistic that would be. Doing this based on the driver
> > / cmdline preference is going to be fairly easy, but then it's a
> > property, it's going to be updated, and we probably don't want to mess
> > around the mode flags based on new property values?
> > 
> 
> Strictly speaking we need to fire an event to userspace if the mode
> changes, and this is probably not straightforward to do underneath
> modeset locks, would probably need a worker.

I'm not sure this would work in all cases. Kodi for example doesn't
handle hotplug events at all, so we might end up in situations where the
state is not consistent anymore.

Even if we were to only expose one mode to the userspace, depending on
the current TV mode, userspace could still end up trying to push a mode
into KMS that isn't the one we expose anymore, so I'm not sure we can
solve this entirely.

> Clever userspace like GNOME will try to use the active mode, so it will
> handle this that way. If someone has set up the pipeline first that is.
> drm_client/fbdev and plymouth can do that because they honour userdef modes.
> 
> Other userspace that don't know the userdef flag will fallback to the
> first mode which is NTSC which is also the default tvmode, so maybe this
> is good enough. PAL users will have to specify the mode, or teach their
> program about the userdef flag.
> 
> But ofc relying on the userdef flag depends on the fact that there's a
> mode on the kernel command line, but maybe there's no way to avoid that
> since much/most? userspace treat "unknown" connector status as
> disconnected so many will have to force the connector to "connected"
> anyway. At least I don't know any way to permanetly force the connector
> status other than using video=.

You can do it through sysfs as well, in .../status

Maxime


signature.asc
Description: PGP signature


Re: [PATCH 4/4] vfio/pci: Allow MMIO regions to be exported through dma-buf

2022-08-29 Thread Jason Gunthorpe
On Mon, Aug 29, 2022 at 01:04:05PM +0800, Yan Zhao wrote:

> > +static struct sg_table *
> > +vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment,
> > +enum dma_data_direction dir)
> > +{
> > +   size_t sgl_size = dma_get_max_seg_size(attachment->dev);
> > +   struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
> > +   struct scatterlist *sgl;
> > +   struct sg_table *sgt;
> > +   dma_addr_t dma_addr;
> > +   unsigned int nents;
> > +   size_t offset;
> > +   int ret;
> > +
> > +   dma_resv_assert_held(priv->dmabuf->resv);
> > +
> > +   if (!attachment->peer2peer)
> > +   return ERR_PTR(-EPERM);
> > +
> > +   if (!priv->revoked)
> > +   return ERR_PTR(-ENODEV);
> > +
> > +   sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
> > +   if (!sgt)
> > +   return ERR_PTR(-ENOMEM);
> > +
> > +   nents = DIV_ROUND_UP(priv->dmabuf->size, sgl_size);
> > +   ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
> > +   if (ret)
> > +   goto err_kfree_sgt;
> > +
> > +   /*
> > +* Since the memory being mapped is a device memory it could never be in
> > +* CPU caches.
> > +*/
> > +   dma_addr = dma_map_resource(
> > +   attachment->dev,
> > +   pci_resource_start(priv->vdev->pdev, priv->index) +
> > +   priv->offset,
> > +   priv->dmabuf->size, dir, DMA_ATTR_SKIP_CPU_SYNC);
> dma_map_resource maps the phys to an IOVA in device's
> default_domain, which, however, may not be the domain that the device is
> currently attached to.

dmabuf is defined only in terms of the DMA API, so it creates a SGL
with DMA API mapped dma_addr's

> So, the importer of this sgt will convert this dma_addr back to phys?

No, it is illegal to call this API if the importer is not using the
DMA API.

I'm expecting to propose some new dmabuf API for this use-case, when
we get to it. For now all importers use the DMA API.

> BTW, I don't see the assignment of priv->index in below
> vfio_pci_core_feature_dma_buf(), is it equal to
> get_dma_buf.region_index ?

Yes, I noticed that too and have fixed it - the testing was all done
on index 0.

Jason


[PATCH linux-next] drm/amdkfd: remove redundant variables err and ret

2022-08-29 Thread cgel . zte
From: Jinpeng Cui 

Return value from kfd_wait_on_events() and io_remap_pfn_range() directly
instead of taking this in another redundant variable.

Reported-by: Zeal Robot 
Signed-off-by: Jinpeng Cui 
---
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 664e8b5d82c0..84da1a9ce37c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -876,14 +876,11 @@ static int kfd_ioctl_wait_events(struct file *filp, 
struct kfd_process *p,
void *data)
 {
struct kfd_ioctl_wait_events_args *args = data;
-   int err;
 
-   err = kfd_wait_on_events(p, args->num_events,
+   return kfd_wait_on_events(p, args->num_events,
(void __user *)args->events_ptr,
(args->wait_for_all != 0),
&args->timeout, &args->wait_result);
-
-   return err;
 }
 static int kfd_ioctl_set_scratch_backing_va(struct file *filep,
struct kfd_process *p, void *data)
@@ -2860,7 +2857,6 @@ static int kfd_mmio_mmap(struct kfd_dev *dev, struct 
kfd_process *process,
  struct vm_area_struct *vma)
 {
phys_addr_t address;
-   int ret;
 
if (vma->vm_end - vma->vm_start != PAGE_SIZE)
return -EINVAL;
@@ -2880,12 +2876,11 @@ static int kfd_mmio_mmap(struct kfd_dev *dev, struct 
kfd_process *process,
 process->pasid, (unsigned long long) vma->vm_start,
 address, vma->vm_flags, PAGE_SIZE);
 
-   ret = io_remap_pfn_range(vma,
+   return io_remap_pfn_range(vma,
vma->vm_start,
address >> PAGE_SHIFT,
PAGE_SIZE,
vma->vm_page_prot);
-   return ret;
 }
 
 
-- 
2.25.1



[PATCH v2 00/41] drm: Analog TV Improvements

2022-08-29 Thread Maxime Ripard
Hi,

Here's a series aiming at improving the command line named modes support,
and more importantly how we deal with all the analog TV variants.

The named modes support were initially introduced to allow to specify the
analog TV mode to be used.

However, this was causing multiple issues:

  * The mode name parsed on the command line was passed directly to the
driver, which had to figure out which mode it was suppose to match;

  * Figuring that out wasn't really easy, since the video= argument or what
the userspace might not even have a name in the first place, but
instead could have passed a mode with the same timings;

  * The fallback to matching on the timings was mostly working as long as
we were supporting one 525 lines (most likely NSTC) and one 625 lines
(PAL), but couldn't differentiate between two modes with the same
timings (NTSC vs PAL-M vs NSTC-J for example);

  * There was also some overlap with the tv mode property registered by
drm_mode_create_tv_properties(), but named modes weren't interacting
with that property at all.

  * Even though that property was generic, its possible values were
specific to each drivers, which made some generic support difficult.

Thus, I chose to tackle in multiple steps:

  * A new TV norm property was introduced, with generic values, each driver
reporting through a bitmask what standard it supports to the userspace;

  * This option was added to the command line parsing code to be able to
specify it on the kernel command line, and new atomic_check and reset
helpers were created to integrate properly into atomic KMS;

  * The named mode parsing code is now creating a proper display mode for
the given named mode, and the TV standard will thus be part of the
connector state;

  * Two drivers were converted and tested for now (vc4 and sun4i), with
some backward compatibility code to translate the old TV mode to the
new TV mode;

Unit tests were created along the way.

One can switch from NTSC to PAL now using (on vc4)

modetest -M vc4  -s 53:720x480i -w 53:'tv norm':0

modetest -M vc4 -s 53:720x480i -w 53:'tv norm':4

Let me know what you think,
Maxime

Changes from v1 
(https://lore.kernel.org/dri-devel/20220728-rpi-analog-tv-properties-v1-0-3d53ae722...@cerno.tech/):
  - Kept the older TV mode property as legacy so we can keep the old drivers 
functional
  - Renamed the tv_norm property to tv_mode
  - Added a function to create PAL and NTSC compatible display modes
  - Added some helpers to instantiate a mock DRM device in Kunit
  - More Kunit tests
  - Removed the HD analog TV modes
  - Renamed some of the tests
  - Renamed some of the named modes
  - Fixed typos in commit logs
  - Added the various tags

Cc: Geert Uytterhoeven 
Cc: Mateusz Kwiatkowski 
Cc: "Noralf Trønnes" 
Cc: Dave Stevenson 
Cc: Dom Cobley 
Cc: Phil Elwell 
Cc: 

---
Geert Uytterhoeven (1):
  drm/modes: parse_cmdline: Add support for named modes containing dashes

Mateusz Kwiatkowski (5):
  drm/vc4: vec: Refactor VEC TV mode setting
  drm/vc4: vec: Remove redundant atomic_mode_set
  drm/vc4: vec: Fix timings for VEC modes
  drm/vc4: vec: Fix definition of PAL-M mode
  drm/vc4: vec: Add support for more analog TV standards

Maxime Ripard (35):
  drm/tests: Order Kunit tests in Makefile
  drm/tests: Add Kunit Helpers
  drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid 
ambiguity
  drm/connector: Rename subconnector state variable
  drm/atomic: Add TV subconnector property to get/set_property
  drm/connector: Rename legacy TV property
  drm/connector: Only register TV mode property if present
  drm/connector: Rename drm_mode_create_tv_properties
  drm/connector: Add TV standard property
  drm/modes: Add a function to generate analog display modes
  drm/modes: Only consider bpp and refresh before options
  drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  drm/modes: Move named modes parsing to a separate function
  drm/modes: Switch to named mode descriptors
  drm/modes: Fill drm_cmdline mode from named modes
  drm/connector: Add pixel clock to cmdline mode
  drm/connector: Add a function to lookup a TV mode by its name
  drm/modes: Introduce the tv_mode property as a command-line option
  drm/modes: Properly generate a drm_display_mode from a named mode
  drm/modes: Introduce more named modes
  drm/atomic-helper: Add a TV properties reset helper
  drm/atomic-helper: Add an analog TV atomic_check implementation
  drm/vc4: vec: Remove empty mode_fixup
  drm/vc4: vec: Convert to atomic helpers
  drm/vc4: vec: Switch for common modes
  drm/vc4: vec: Use TV Reset implementation
  drm/vc4: vec: Convert to the new TV mode property
  drm/sun4i: tv: Remove unused mode_valid
  drm/sun4i: tv: Convert to atomic hooks
  drm/sun4i: tv: Merge mode_set into atomic_

[PATCH v2 01/41] drm/tests: Order Kunit tests in Makefile

2022-08-29 Thread Maxime Ripard
Since we've recently added a ton of tests, the list starts to be a bit
of a mess and creates unneeded conflicts.

Let's order it alphabetically.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 91b70f7d2769..2d9f49b62ecb 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -1,5 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o 
drm_damage_helper_test.o \
-   drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o 
drm_plane_helper_test.o \
-   drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o 
drm_mm_test.o
+obj-$(CONFIG_DRM_KUNIT_TEST) += \
+   drm_buddy_test.o \
+   drm_cmdline_parser_test.o \
+   drm_damage_helper_test.o \
+   drm_dp_mst_helper_test.o \
+   drm_format_helper_test.o \
+   drm_format_test.o \
+   drm_framebuffer_test.o \
+   drm_mm_test.o \
+   drm_plane_helper_test.o \
+   drm_rect_test.o

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 02/41] drm/tests: Add Kunit Helpers

2022-08-29 Thread Maxime Ripard
As the number of kunit tests in KMS grows further, we start to have
multiple test suites that, for example, need to register a mock DRM
driver to interact with the KMS function they are supposed to test.

Let's add a file meant to provide those kind of helpers to avoid
duplication.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 2d9f49b62ecb..b29ef1085cad 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
drm_format_helper_test.o \
drm_format_test.o \
drm_framebuffer_test.o \
+   drm_kunit_helpers.o \
drm_mm_test.o \
drm_plane_helper_test.o \
drm_rect_test.o
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c 
b/drivers/gpu/drm/tests/drm_kunit_helpers.c
new file mode 100644
index ..7ebd620481c1
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
@@ -0,0 +1,54 @@
+#include 
+#include 
+
+#include 
+
+static const struct drm_mode_config_funcs drm_mode_config_funcs = {
+};
+
+static const struct drm_driver drm_mode_driver = {
+};
+
+static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
+{
+   struct device *dev = ptr;
+
+   root_device_unregister(dev);
+}
+
+struct drm_device *drm_kunit_device_init(const char *name)
+{
+   struct drm_device *drm;
+   struct device *dev;
+   int ret;
+
+   dev = root_device_register(name);
+   if (IS_ERR(dev))
+   return ERR_CAST(dev);
+
+   drm = drm_dev_alloc(&drm_mode_driver, dev);
+   if (IS_ERR(drm)) {
+   root_device_unregister(dev);
+   return ERR_CAST(drm);
+   }
+   drm->mode_config.funcs = &drm_mode_config_funcs;
+
+   ret = drmm_add_action_or_reset(drm, drm_kunit_free_device, dev);
+   if (ret)
+   goto err_put_device;
+
+   ret = drmm_mode_config_init(drm);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return drm;
+
+err_put_device:
+   drm_dev_put(drm);
+   return ERR_PTR(ret);
+}
+
+void drm_kunit_device_exit(struct drm_device *drm)
+{
+   drm_dev_put(drm);
+}
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h 
b/drivers/gpu/drm/tests/drm_kunit_helpers.h
new file mode 100644
index ..5015a327a8c1
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.h
@@ -0,0 +1,9 @@
+#ifndef DRM_KUNIT_HELPERS_H_
+#define DRM_KUNIT_HELPERS_H_
+
+struct drm_device;
+
+struct drm_device *drm_kunit_device_init(const char *name);
+void drm_kunit_device_exit(struct drm_device *drm);
+
+#endif // DRM_KUNIT_HELPERS_H_

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 04/41] drm/connector: Rename subconnector state variable

2022-08-29 Thread Maxime Ripard
There is two TV subconnector related properties registered by
drm_mode_create_tv_properties(): subconnector and select subconnector.

While the select subconnector property is stored in the kernel by the
drm_tv_connector_state structure, the subconnector property isn't stored
anywhere.

Worse, the select subconnector property is stored in a field called
subconnector, creating some ambiguity about which property content we're
accessing.

Let's rename that field to one called select_subconnector to make it move
obvious what it's about.

Signed-off-by: Maxime Ripard 
Reviewed-by: Noralf Trønnes 

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 79730fa1dd8e..c74c78a28171 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -687,7 +687,7 @@ static int drm_atomic_connector_set_property(struct 
drm_connector *connector,
 */
return -EINVAL;
} else if (property == config->tv_select_subconnector_property) {
-   state->tv.subconnector = val;
+   state->tv.select_subconnector = val;
} else if (property == config->tv_left_margin_property) {
state->tv.margins.left = val;
} else if (property == config->tv_right_margin_property) {
@@ -795,7 +795,7 @@ drm_atomic_connector_get_property(struct drm_connector 
*connector,
else
*val = connector->dpms;
} else if (property == config->tv_select_subconnector_property) {
-   *val = state->tv.subconnector;
+   *val = state->tv.select_subconnector;
} else if (property == config->tv_left_margin_property) {
*val = state->tv.margins.left;
} else if (property == config->tv_right_margin_property) {
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 23112f0c11cf..60b5662dec7c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -703,7 +703,7 @@ struct drm_connector_tv_margins {
  * @hue: hue in percent
  */
 struct drm_tv_connector_state {
-   enum drm_mode_subconnector subconnector;
+   enum drm_mode_subconnector select_subconnector;
struct drm_connector_tv_margins margins;
unsigned int mode;
unsigned int brightness;

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 05/41] drm/atomic: Add TV subconnector property to get/set_property

2022-08-29 Thread Maxime Ripard
The subconnector property was created by drm_mode_create_tv_properties(),
but wasn't exposed to the userspace through the generic
atomic_get/set_property implementation, and wasn't stored in any generic
state structure.

Let's solve this.

Signed-off-by: Maxime Ripard 
Reviewed-by: Noralf Trønnes 

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index c74c78a28171..c06d0639d552 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -688,6 +688,8 @@ static int drm_atomic_connector_set_property(struct 
drm_connector *connector,
return -EINVAL;
} else if (property == config->tv_select_subconnector_property) {
state->tv.select_subconnector = val;
+   } else if (property == config->tv_subconnector_property) {
+   state->tv.subconnector = val;
} else if (property == config->tv_left_margin_property) {
state->tv.margins.left = val;
} else if (property == config->tv_right_margin_property) {
@@ -796,6 +798,8 @@ drm_atomic_connector_get_property(struct drm_connector 
*connector,
*val = connector->dpms;
} else if (property == config->tv_select_subconnector_property) {
*val = state->tv.select_subconnector;
+   } else if (property == config->tv_subconnector_property) {
+   *val = state->tv.subconnector;
} else if (property == config->tv_left_margin_property) {
*val = state->tv.margins.left;
} else if (property == config->tv_right_margin_property) {
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 60b5662dec7c..1d5e3cccb9e3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -693,6 +693,7 @@ struct drm_connector_tv_margins {
 /**
  * struct drm_tv_connector_state - TV connector related states
  * @select_subconnector: selected subconnector
+ * @subconnector: detected subconnector
  * @margins: TV margins
  * @mode: TV mode
  * @brightness: brightness in percent
@@ -704,6 +705,7 @@ struct drm_connector_tv_margins {
  */
 struct drm_tv_connector_state {
enum drm_mode_subconnector select_subconnector;
+   enum drm_mode_subconnector subconnector;
struct drm_connector_tv_margins margins;
unsigned int mode;
unsigned int brightness;

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 03/41] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity

2022-08-29 Thread Maxime Ripard
We currently have two sets of TV properties.

The first one is there to deal with analog TV properties, creating
properties such as the TV mode, subconnectors, saturation, hue and so on.
It's created by calling the drm_mode_create_tv_properties() function.

The second one is there to deal with properties that might be useful on a
TV, creating the overscan margins for example. It's created by calling the
drm_mode_create_tv_margin_properties().

However, we also have a drm_atomic_helper_connector_tv_reset() function
that will reset the TV margin properties to their default values, and thus
is supposed to be called for the latter set. This creates an ambiguity due
to the inconsistent naming.

We can thus rename the drm_atomic_helper_connector_tv_reset() function to
drm_atomic_helper_connector_tv_margins_reset() to remove that ambiguity
and hopefully make it more obvious.

Signed-off-by: Maxime Ripard 
Reviewed-by: Noralf Trønnes 

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index bf31b9d92094..dfb57217253b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -464,12 +464,12 @@ void drm_atomic_helper_connector_reset(struct 
drm_connector *connector)
 EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
 
 /**
- * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
+ * drm_atomic_helper_connector_tv_margins_reset - Resets TV connector 
properties
  * @connector: DRM connector
  *
  * Resets the TV-related properties attached to a connector.
  */
-void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
+void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector 
*connector)
 {
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
struct drm_connector_state *state = connector->state;
@@ -479,7 +479,7 @@ void drm_atomic_helper_connector_tv_reset(struct 
drm_connector *connector)
state->tv.margins.top = cmdline->tv_margins.top;
state->tv.margins.bottom = cmdline->tv_margins.bottom;
 }
-EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
 
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
diff --git a/drivers/gpu/drm/gud/gud_connector.c 
b/drivers/gpu/drm/gud/gud_connector.c
index d0addd478815..fa636206f232 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -355,7 +355,7 @@ static void gud_connector_reset(struct drm_connector 
*connector)
drm_atomic_helper_connector_reset(connector);
connector->state->tv = gconn->initial_tv_state;
/* Set margins from command line */
-   drm_atomic_helper_connector_tv_reset(connector);
+   drm_atomic_helper_connector_tv_margins_reset(connector);
if (gconn->initial_brightness >= 0)
connector->state->tv.brightness = gconn->initial_brightness;
 }
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 84e5a91c2ea7..6877add8e1fa 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -396,7 +396,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector 
*connector)
new_state->base.max_bpc = 8;
new_state->base.max_requested_bpc = 8;
new_state->output_format = VC4_HDMI_OUTPUT_RGB;
-   drm_atomic_helper_connector_tv_reset(connector);
+   drm_atomic_helper_connector_tv_margins_reset(connector);
 }
 
 static struct drm_connector_state *
diff --git a/include/drm/drm_atomic_state_helper.h 
b/include/drm/drm_atomic_state_helper.h
index 3f8f1d627f7c..192766656b88 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -70,7 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct 
drm_connector_state *conn_
 void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
 struct drm_connector_state 
*conn_state);
 void drm_atomic_helper_connector_reset(struct drm_connector *connector);
-void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector 
*connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
   struct drm_connector_state *state);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 248206bbd975..23112f0c11cf 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -692,7 +692,7 @@ struct drm_connector_tv_margins {
 
 /**
  * struct drm_tv_connector_state - TV connector related states
- * @subconnector: selected subconnector
+ * @select_subconnector: selected subconnector
  * @margins: TV margins
  * @mode: TV mode
  * @brightness: brightness in percent

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 07/41] drm/connector: Only register TV mode property if present

2022-08-29 Thread Maxime Ripard
The drm_create_tv_properties() will create the TV mode property
unconditionally.

However, since we'll gradually phase it out, let's register it only if we
have a list passed as an argument. This will make the transition easier.

Signed-off-by: Maxime Ripard 
Acked-by: Noralf Trønnes 

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index ede6025638d7..17a5913cefe3 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1686,15 +1686,18 @@ int drm_mode_create_tv_properties(struct drm_device 
*dev,
if (drm_mode_create_tv_margin_properties(dev))
goto nomem;
 
-   dev->mode_config.legacy_tv_mode_property =
-   drm_property_create(dev, DRM_MODE_PROP_ENUM,
-   "mode", num_modes);
-   if (!dev->mode_config.legacy_tv_mode_property)
-   goto nomem;
 
-   for (i = 0; i < num_modes; i++)
-   drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
- i, modes[i]);
+   if (num_modes) {
+   dev->mode_config.legacy_tv_mode_property =
+   drm_property_create(dev, DRM_MODE_PROP_ENUM,
+   "mode", num_modes);
+   if (!dev->mode_config.legacy_tv_mode_property)
+   goto nomem;
+
+   for (i = 0; i < num_modes; i++)
+   
drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
+ i, modes[i]);
+   }
 
dev->mode_config.tv_brightness_property =
drm_property_create_range(dev, 0, "brightness", 0, 100);

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 08/41] drm/connector: Rename drm_mode_create_tv_properties

2022-08-29 Thread Maxime Ripard
drm_mode_create_tv_properties(), among other things, will create the
"mode" property that stores the analog TV mode that connector is
supposed to output.

However, that property is getting deprecated, so let's rename that
function to mention it's deprecated. We'll introduce a new variant of
that function creating the property superseeding it in a later patch.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 17a5913cefe3..4e4fbc9e0049 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1600,7 +1600,7 @@ EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
  * Called by a driver's HDMI connector initialization routine, this function
  * creates the TV margin properties for a given device. No need to call this
  * function for an SDTV connector, it's already called from
- * drm_mode_create_tv_properties().
+ * drm_mode_create_tv_properties_legacy().
  *
  * Returns:
  * 0 on success or a negative error code on failure.
@@ -1635,7 +1635,7 @@ int drm_mode_create_tv_margin_properties(struct 
drm_device *dev)
 EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
 
 /**
- * drm_mode_create_tv_properties - create TV specific connector properties
+ * drm_mode_create_tv_properties_legacy - create TV specific connector 
properties
  * @dev: DRM device
  * @num_modes: number of different TV formats (modes) supported
  * @modes: array of pointers to strings containing name of each format
@@ -1648,9 +1648,9 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
  * Returns:
  * 0 on success or a negative error code on failure.
  */
-int drm_mode_create_tv_properties(struct drm_device *dev,
- unsigned int num_modes,
- const char * const modes[])
+int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
+unsigned int num_modes,
+const char * const modes[])
 {
struct drm_property *tv_selector;
struct drm_property *tv_subconnector;
@@ -1733,7 +1733,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 nomem:
return -ENOMEM;
 }
-EXPORT_SYMBOL(drm_mode_create_tv_properties);
+EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
 
 /**
  * drm_mode_create_scaling_mode_property - create scaling mode property
diff --git a/drivers/gpu/drm/gud/gud_connector.c 
b/drivers/gpu/drm/gud/gud_connector.c
index caf82e9095b4..4026eb0132bd 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -400,7 +400,7 @@ static int gud_connector_add_tv_mode(struct gud_device 
*gdrm, struct drm_connect
for (i = 0; i < num_modes; i++)
modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN];
 
-   ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes);
+   ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, 
modes);
 free:
kfree(buf);
if (ret < 0)
@@ -539,7 +539,7 @@ static int gud_connector_add_properties(struct gud_device 
*gdrm, struct gud_conn
fallthrough;
case GUD_PROPERTY_TV_HUE:
/* This is a no-op if already added. */
-   ret = drm_mode_create_tv_properties(drm, 0, NULL);
+   ret = drm_mode_create_tv_properties_legacy(drm, 0, 
NULL);
if (ret)
goto out;
break;
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index d29b63fd6178..506f6f932518 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -250,7 +250,7 @@ static int ch7006_encoder_create_resources(struct 
drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_mode_config *conf = &dev->mode_config;
 
-   drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
+   drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, 
ch7006_tv_norm_names);
 
priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2);
if (!priv->scale_property)
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c 
b/drivers/gpu/drm/i915/display/intel_tv.c
index 9379f3463344..7fd2c6f01ad6 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1984,7 +1984,7 @@ intel_tv_init(struct drm_i915_private *dev_priv)
 
tv_format_names[i] = tv_modes[i].name;
}
-   drm_mode_create_tv_properties(dev, i, tv_format_names);
+   drm_mode_create_tv_properties_legacy(dev, i, tv_format_names);
 
drm_object_attach_property(&connector->base, 
dev->mode_config.tv_mode_property,
   state->tv.mode);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c 
b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
inde

[PATCH v2 10/41] drm/modes: Add a function to generate analog display modes

2022-08-29 Thread Maxime Ripard
Multiple drivers (meson, vc4, sun4i) define analog TV 525-lines and
625-lines modes in their drivers.

Since those modes are fairly standard, and that we'll need to use them
in more places in the future, it makes sense to move their definition
into the core framework.

However, analog display usually have fairly loose timings requirements,
the only discrete parameters being the total number of lines and pixel
clock frequency. Thus, we created a function that will create a display
mode from the standard, the pixel frequency and the active area.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 304004fb80aa..ee581ee17171 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -116,6 +116,459 @@ void drm_mode_probed_add(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_probed_add);
 
+enum drm_mode_analog {
+   DRM_MODE_ANALOG_NTSC,
+   DRM_MODE_ANALOG_PAL,
+};
+
+/*
+ * The timings come from:
+ * - 
https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
+ * - 
https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
+ * - 
https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
+ */
+#define NTSC_LINE_DURATION_NS  63556U
+#define NTSC_LINES_NUMBER  525
+
+#define NTSC_HBLK_DURATION_TYP_NS  10900U
+#define NTSC_HBLK_DURATION_MIN_NS  (NTSC_HBLK_DURATION_TYP_NS - 200)
+#define NTSC_HBLK_DURATION_MAX_NS  (NTSC_HBLK_DURATION_TYP_NS + 200)
+
+#define NTSC_HACT_DURATION_TYP_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_TYP_NS)
+#define NTSC_HACT_DURATION_MIN_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_MAX_NS)
+#define NTSC_HACT_DURATION_MAX_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_MIN_NS)
+
+#define NTSC_HFP_DURATION_TYP_NS   1500
+#define NTSC_HFP_DURATION_MIN_NS   1270
+#define NTSC_HFP_DURATION_MAX_NS   2220
+
+#define NTSC_HSLEN_DURATION_TYP_NS 4700
+#define NTSC_HSLEN_DURATION_MIN_NS (NTSC_HSLEN_DURATION_TYP_NS - 100)
+#define NTSC_HSLEN_DURATION_MAX_NS (NTSC_HSLEN_DURATION_TYP_NS + 100)
+
+#define NTSC_HBP_DURATION_TYP_NS   4700
+
+/*
+ * I couldn't find the actual tolerance for the back porch, so let's
+ * just reuse the sync length ones.
+ */
+#define NTSC_HBP_DURATION_MIN_NS   (NTSC_HBP_DURATION_TYP_NS - 100)
+#define NTSC_HBP_DURATION_MAX_NS   (NTSC_HBP_DURATION_TYP_NS + 100)
+
+#define PAL_LINE_DURATION_NS   64000U
+#define PAL_LINES_NUMBER   625
+
+#define PAL_HACT_DURATION_TYP_NS   51950U
+#define PAL_HACT_DURATION_MIN_NS   (PAL_HACT_DURATION_TYP_NS - 100)
+#define PAL_HACT_DURATION_MAX_NS   (PAL_HACT_DURATION_TYP_NS + 400)
+
+#define PAL_HBLK_DURATION_TYP_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_TYP_NS)
+#define PAL_HBLK_DURATION_MIN_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_MAX_NS)
+#define PAL_HBLK_DURATION_MAX_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_MIN_NS)
+
+#define PAL_HFP_DURATION_TYP_NS1650
+#define PAL_HFP_DURATION_MIN_NS(PAL_HFP_DURATION_TYP_NS - 100)
+#define PAL_HFP_DURATION_MAX_NS(PAL_HFP_DURATION_TYP_NS + 400)
+
+#define PAL_HSLEN_DURATION_TYP_NS  4700
+#define PAL_HSLEN_DURATION_MIN_NS  (PAL_HSLEN_DURATION_TYP_NS - 200)
+#define PAL_HSLEN_DURATION_MAX_NS  (PAL_HSLEN_DURATION_TYP_NS + 200)
+
+#define PAL_HBP_DURATION_TYP_NS5700
+#define PAL_HBP_DURATION_MIN_NS(PAL_HBP_DURATION_TYP_NS - 200)
+#define PAL_HBP_DURATION_MAX_NS(PAL_HBP_DURATION_TYP_NS + 200)
+
+#define PAL_VFP_INTERLACE_LINES5
+#define PAL_VSLEN_INTERLACE_LINES  5
+
+#define PAL_SHORT_SYNC_DURATION_NS ((2 + 30) * NSEC_PER_USEC)
+#define PAL_LONG_SYNC_DURATION_NS  ((30 + 2) * NSEC_PER_USEC)
+
+struct analog_param_field {
+   unsigned int even, odd;
+};
+
+#define PARAM_FIELD(_odd, _even)   \
+   { .even = _even, .odd = _odd }
+
+struct analog_param_range {
+   unsigned intmin, typ, max;
+};
+
+#define PARAM_RANGE(_min, _typ, _max)  \
+   { .min = _min, .typ = _typ, .max = _max }
+
+struct analog_parameters {
+   unsigned intnum_lines;
+   unsigned intline_duration_ns;
+
+   struct analog_param_range   hact_ns;
+   struct analog_param_range   hfp_ns;
+   struct analog_param_range   hslen_ns;
+   struct analog_param_range   hbp_ns;
+   struct analog_param_range   hblk_ns;
+
+   struct analog_param_field   vfp_lines;
+   struct analog_param_field   vslen_lines;
+   struct analog_param_field   vbp_lines;
+};
+
+#define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, _hslen, _hbp, 
_hblk, _vfp, _vslen, _vbp) \
+   [_mode] = { \
+

[PATCH v2 11/41] drm/modes: Only consider bpp and refresh before options

2022-08-29 Thread Maxime Ripard
Some video= options might have a value that contains a dash. However, the
command line parsing mode considers all dashes as the separator between the
mode and the bpp count.

Let's rework the parsing code a bit to only consider a dash as the bpp
separator if it before a comma, the options separator.

A follow-up patch will add a unit-test for this once such an option is
introduced.

Signed-off-by: Maxime Ripard 
Reviewed-by: Geert Uytterhoeven 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index ee581ee17171..b4e1ff56b4d8 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2254,20 +2254,22 @@ bool drm_mode_parse_command_line_for_connector(const 
char *mode_option,
 
name = mode_option;
 
+   /* Locate the start of named options */
+   options_ptr = strchr(name, ',');
+   if (options_ptr)
+   options_off = options_ptr - name;
+   else
+   options_off = strlen(name);
+
/* Try to locate the bpp and refresh specifiers, if any */
-   bpp_ptr = strchr(name, '-');
+   bpp_ptr = strnchr(name, options_off, '-');
if (bpp_ptr)
bpp_off = bpp_ptr - name;
 
-   refresh_ptr = strchr(name, '@');
+   refresh_ptr = strnchr(name, options_off, '@');
if (refresh_ptr)
refresh_off = refresh_ptr - name;
 
-   /* Locate the start of named options */
-   options_ptr = strchr(name, ',');
-   if (options_ptr)
-   options_off = options_ptr - name;
-
/* Locate the end of the name / resolution, and parse it */
if (bpp_ptr) {
mode_end = bpp_off;

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 06/41] drm/connector: Rename legacy TV property

2022-08-29 Thread Maxime Ripard
The current tv_mode has driver-specific values that don't allow to
easily share code using it, either at the userspace or kernel level.

Since we're going to introduce a new, generic, property that fit the
same purpose, let's rename this one to legacy_tv_mode to make it
obvious we should move away from it.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index c06d0639d552..7f2b9a07fbdf 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -698,8 +698,8 @@ static int drm_atomic_connector_set_property(struct 
drm_connector *connector,
state->tv.margins.top = val;
} else if (property == config->tv_bottom_margin_property) {
state->tv.margins.bottom = val;
-   } else if (property == config->tv_mode_property) {
-   state->tv.mode = val;
+   } else if (property == config->legacy_tv_mode_property) {
+   state->tv.legacy_mode = val;
} else if (property == config->tv_brightness_property) {
state->tv.brightness = val;
} else if (property == config->tv_contrast_property) {
@@ -808,8 +808,8 @@ drm_atomic_connector_get_property(struct drm_connector 
*connector,
*val = state->tv.margins.top;
} else if (property == config->tv_bottom_margin_property) {
*val = state->tv.margins.bottom;
-   } else if (property == config->tv_mode_property) {
-   *val = state->tv.mode;
+   } else if (property == config->legacy_tv_mode_property) {
+   *val = state->tv.legacy_mode;
} else if (property == config->tv_brightness_property) {
*val = state->tv.brightness;
} else if (property == config->tv_contrast_property) {
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index e3142c8142b3..ede6025638d7 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1686,14 +1686,14 @@ int drm_mode_create_tv_properties(struct drm_device 
*dev,
if (drm_mode_create_tv_margin_properties(dev))
goto nomem;
 
-   dev->mode_config.tv_mode_property =
+   dev->mode_config.legacy_tv_mode_property =
drm_property_create(dev, DRM_MODE_PROP_ENUM,
"mode", num_modes);
-   if (!dev->mode_config.tv_mode_property)
+   if (!dev->mode_config.legacy_tv_mode_property)
goto nomem;
 
for (i = 0; i < num_modes; i++)
-   drm_property_add_enum(dev->mode_config.tv_mode_property,
+   drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
  i, modes[i]);
 
dev->mode_config.tv_brightness_property =
diff --git a/drivers/gpu/drm/gud/gud_connector.c 
b/drivers/gpu/drm/gud/gud_connector.c
index fa636206f232..caf82e9095b4 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -424,7 +424,7 @@ gud_connector_property_lookup(struct drm_connector 
*connector, u16 prop)
case GUD_PROPERTY_TV_BOTTOM_MARGIN:
return config->tv_bottom_margin_property;
case GUD_PROPERTY_TV_MODE:
-   return config->tv_mode_property;
+   return config->legacy_tv_mode_property;
case GUD_PROPERTY_TV_BRIGHTNESS:
return config->tv_brightness_property;
case GUD_PROPERTY_TV_CONTRAST:
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index b91e48d2190d..d29b63fd6178 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -264,7 +264,7 @@ static int ch7006_encoder_create_resources(struct 
drm_encoder *encoder,
  priv->hmargin);
drm_object_attach_property(&connector->base, 
conf->tv_bottom_margin_property,
  priv->vmargin);
-   drm_object_attach_property(&connector->base, conf->tv_mode_property,
+   drm_object_attach_property(&connector->base, 
conf->legacy_tv_mode_property,
  priv->norm);
drm_object_attach_property(&connector->base, 
conf->tv_brightness_property,
  priv->brightness);
@@ -315,7 +315,7 @@ static int ch7006_encoder_set_property(struct drm_encoder 
*encoder,
ch7006_load_reg(client, state, CH7006_POV);
ch7006_load_reg(client, state, CH7006_VPOS);
 
-   } else if (property == conf->tv_mode_property) {
+   } else if (property == conf->legacy_tv_mode_property) {
if (connector->dpms != DRM_MODE_DPMS_OFF)
return -EINVAL;
 
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c 
b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index be28e7bd7490..1a15534adc60 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/d

[PATCH v2 13/41] drm/client: Add some tests for drm_connector_pick_cmdline_mode()

2022-08-29 Thread Maxime Ripard
drm_connector_pick_cmdline_mode() is in charge of finding a proper
drm_display_mode from the definition we got in the video= command line
argument.

Let's add some unit tests to make sure we're not getting any regressions
there.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index bbc535cc50dd..d553e793e673 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev 
*client, int mode)
return ret;
 }
 EXPORT_SYMBOL(drm_client_modeset_dpms);
+
+#ifdef CONFIG_DRM_KUNIT_TEST
+#include "tests/drm_client_modeset_test.c"
+#endif
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c 
b/drivers/gpu/drm/tests/drm_client_modeset_test.c
new file mode 100644
index ..46335de7bc6b
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Maxime Ripard 
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "drm_kunit_helpers.h"
+
+struct drm_client_modeset_test_priv {
+   struct drm_device *drm;
+   struct drm_connector connector;
+};
+
+static int drm_client_modeset_connector_get_modes(struct drm_connector 
*connector)
+{
+   struct drm_display_mode *mode;
+   int count;
+
+   count = drm_add_modes_noedid(connector, 1920, 1200);
+
+   return count;
+}
+
+static const struct drm_connector_helper_funcs 
drm_client_modeset_connector_helper_funcs = {
+   .get_modes = drm_client_modeset_connector_get_modes,
+};
+
+static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
+};
+
+static int drm_client_modeset_test_init(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv;
+   int ret;
+
+   priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+   test->priv = priv;
+
+   priv->drm = drm_kunit_device_init("drm-client-modeset-test");
+   if (IS_ERR(priv->drm))
+   return PTR_ERR(priv->drm);
+
+   ret = drmm_connector_init(priv->drm, &priv->connector,
+ &drm_client_modeset_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown,
+ NULL);
+   if (ret)
+   return ret;
+   drm_connector_helper_add(&priv->connector, 
&drm_client_modeset_connector_helper_funcs);
+
+   return 0;
+}
+
+static void drm_client_modeset_test_exit(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv = test->priv;
+
+   drm_kunit_device_exit(priv->drm);
+}
+
+static void drm_pick_cmdline_res_1920_1080_60(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv = test->priv;
+   struct drm_device *drm = priv->drm;
+   struct drm_connector *connector = &priv->connector;
+   struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+   struct drm_display_mode *expected_mode, *mode;
+   const char *cmdline = "1920x1080@60";
+   int ret;
+
+   expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);
+   KUNIT_ASSERT_PTR_NE(test, expected_mode, NULL);
+
+   KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+   connector,
+   
cmdline_mode));
+
+   mutex_lock(&drm->mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(&drm->mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
+}
+
+static struct kunit_case drm_pick_cmdline_tests[] = {
+   KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
+   {}
+};
+
+static struct kunit_suite drm_pick_cmdline_test_suite = {
+   .name = "drm_pick_cmdline",
+   .init = drm_client_modeset_test_init,
+   .exit = drm_client_modeset_test_exit,
+   .test_cases = drm_pick_cmdline_tests
+};
+
+kunit_test_suite(drm_pick_cmdline_test_suite);
+MODULE_AUTHOR("Maxime Ripard ");
+MODULE_LICENSE("GPL");

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 12/41] drm/modes: parse_cmdline: Add support for named modes containing dashes

2022-08-29 Thread Maxime Ripard
From: Geert Uytterhoeven 

It is fairly common for named video modes to contain dashes (e.g.
"tt-mid" on Atari, "dblntsc-ff" on Amiga).  Currently such mode names
are not recognized, as the dash is considered to be a separator between
mode name and bpp.

Fix this by skipping any dashes that are not followed immediately by a
digit when looking for the separator.

Signed-off-by: Geert Uytterhoeven 
Reviewed-by: Hans de Goede 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index b4e1ff56b4d8..99a21e5cd00d 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2263,6 +2263,8 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
 
/* Try to locate the bpp and refresh specifiers, if any */
bpp_ptr = strnchr(name, options_off, '-');
+   while (bpp_ptr && !isdigit(bpp_ptr[1]))
+   bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
if (bpp_ptr)
bpp_off = bpp_ptr - name;
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 09/41] drm/connector: Add TV standard property

2022-08-29 Thread Maxime Ripard
The TV mode property has been around for a while now to select and get the
current TV mode output on an analog TV connector.

Despite that property name being generic, its content isn't and has been
driver-specific which makes it hard to build any generic behaviour on top
of it, both in kernel and user-space.

Let's create a new bitmask tv norm property, that can contain any of the
analog TV standards currently supported by kernel drivers. Each driver can
then pass in a bitmask of the modes it supports.

We'll then be able to phase out the older tv mode property.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 7f2b9a07fbdf..d867e7f9f2cd 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -700,6 +700,8 @@ static int drm_atomic_connector_set_property(struct 
drm_connector *connector,
state->tv.margins.bottom = val;
} else if (property == config->legacy_tv_mode_property) {
state->tv.legacy_mode = val;
+   } else if (property == config->tv_mode_property) {
+   state->tv.mode = val;
} else if (property == config->tv_brightness_property) {
state->tv.brightness = val;
} else if (property == config->tv_contrast_property) {
@@ -810,6 +812,8 @@ drm_atomic_connector_get_property(struct drm_connector 
*connector,
*val = state->tv.margins.bottom;
} else if (property == config->legacy_tv_mode_property) {
*val = state->tv.legacy_mode;
+   } else if (property == config->tv_mode_property) {
+   *val = state->tv.mode;
} else if (property == config->tv_brightness_property) {
*val = state->tv.brightness;
} else if (property == config->tv_contrast_property) {
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4e4fbc9e0049..b1fcacd150e8 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -980,6 +980,29 @@ static const struct drm_prop_enum_list 
drm_dvi_i_subconnector_enum_list[] = {
 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
 drm_dvi_i_subconnector_enum_list)
 
+static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
+   { DRM_MODE_TV_MODE_NTSC_443, "NTSC-443" },
+   { DRM_MODE_TV_MODE_NTSC_J, "NTSC-J" },
+   { DRM_MODE_TV_MODE_NTSC_M, "NTSC-M" },
+   { DRM_MODE_TV_MODE_PAL_60, "PAL-60" },
+   { DRM_MODE_TV_MODE_PAL_B, "PAL-B" },
+   { DRM_MODE_TV_MODE_PAL_D, "PAL-D" },
+   { DRM_MODE_TV_MODE_PAL_G, "PAL-G" },
+   { DRM_MODE_TV_MODE_PAL_H, "PAL-H" },
+   { DRM_MODE_TV_MODE_PAL_I, "PAL-I" },
+   { DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
+   { DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
+   { DRM_MODE_TV_MODE_PAL_NC, "PAL-Nc" },
+   { DRM_MODE_TV_MODE_SECAM_60, "SECAM-60" },
+   { DRM_MODE_TV_MODE_SECAM_B, "SECAM-B" },
+   { DRM_MODE_TV_MODE_SECAM_D, "SECAM-D" },
+   { DRM_MODE_TV_MODE_SECAM_G, "SECAM-G" },
+   { DRM_MODE_TV_MODE_SECAM_K, "SECAM-K" },
+   { DRM_MODE_TV_MODE_SECAM_K1, "SECAM-K1" },
+   { DRM_MODE_TV_MODE_SECAM_L, "SECAM-L" },
+};
+DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
+
 static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
@@ -1645,6 +1668,10 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
  * responsible for allocating a list of format names and passing them to
  * this routine.
  *
+ * NOTE: This functions registers the deprecated "mode" connector
+ * property to select the analog TV mode (ie, NTSC, PAL, etc.). New
+ * drivers must use drm_mode_create_tv_properties() instead.
+ *
  * Returns:
  * 0 on success or a negative error code on failure.
  */
@@ -1686,7 +1713,6 @@ int drm_mode_create_tv_properties_legacy(struct 
drm_device *dev,
if (drm_mode_create_tv_margin_properties(dev))
goto nomem;
 
-
if (num_modes) {
dev->mode_config.legacy_tv_mode_property =
drm_property_create(dev, DRM_MODE_PROP_ENUM,
@@ -1735,6 +1761,46 @@ int drm_mode_create_tv_properties_legacy(struct 
drm_device *dev,
 }
 EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
 
+/**
+ * drm_mode_create_tv_properties - create TV specific connector properties
+ * @dev: DRM device
+ * @supported_tv_modes: Bitmask of TV modes supported (See DRM_MODE_TV_MODE_*)
+
+ * Called by a driver's TV initialization routine, this function creates
+ * the TV specific connector properties for a given device.  Caller is
+ * responsible for allocating a list of format names and passing them to
+ * this routine.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_mode_create_tv_properties(struct drm_device *dev,
+   

[PATCH v2 14/41] drm/modes: Move named modes parsing to a separate function

2022-08-29 Thread Maxime Ripard
The current construction of the named mode parsing doesn't allow to extend
it easily. Let's move it to a separate function so we can add more
parameters and modes.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 99a21e5cd00d..0636cb707544 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1909,6 +1909,9 @@ void drm_connector_list_update(struct drm_connector 
*connector)
 }
 EXPORT_SYMBOL(drm_connector_list_update);
 
+#define STR_STRICT_EQ(str, len, cmp) \
+   ((strlen(cmp) == len) && !strncmp(str, cmp, len))
+
 static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
  struct drm_cmdline_mode *mode)
 {
@@ -2208,6 +2211,52 @@ static const char * const drm_named_modes_whitelist[] = {
"PAL",
 };
 
+static int drm_mode_parse_cmdline_named_mode(const char *name,
+unsigned int name_end,
+struct drm_cmdline_mode 
*cmdline_mode)
+{
+   unsigned int i;
+
+   if (!name_end)
+   return 0;
+
+   /* If the name starts with a digit, it's not a named mode */
+   if (isdigit(name[0]))
+   return 0;
+
+   /*
+* If there's an equal sign in the name, the command-line
+* contains only an option and no mode.
+*/
+   if (strnchr(name, name_end, '='))
+   return 0;
+
+   /* The connection status extras can be set without a mode. */
+   if (STR_STRICT_EQ(name, name_end, "d") ||
+   STR_STRICT_EQ(name, name_end, "D") ||
+   STR_STRICT_EQ(name, name_end, "e"))
+   return 0;
+
+   /*
+* We're sure we're a named mode at that point, iterate over the
+* list of modes we're aware of.
+*/
+   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+   int ret;
+
+   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+   if (ret != name_end)
+   continue;
+
+   strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
+   cmdline_mode->specified = true;
+
+   return 1;
+   }
+
+   return -EINVAL;
+}
+
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for 
connector
  * @mode_option: optional per connector mode option
@@ -2244,7 +2293,7 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
const char *options_ptr = NULL;
char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-   int i, len, ret;
+   int len, ret;
 
memset(mode, 0, sizeof(*mode));
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
@@ -2285,17 +2334,19 @@ bool drm_mode_parse_command_line_for_connector(const 
char *mode_option,
parse_extras = true;
}
 
-   /* First check for a named mode */
-   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
-   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
-   if (ret == mode_end) {
-   if (refresh_ptr)
-   return false; /* named + refresh is invalid */
 
-   strcpy(mode->name, drm_named_modes_whitelist[i]);
-   mode->specified = true;
-   break;
-   }
+   if (mode_end) {
+   ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
+   if (ret < 0)
+   return false;
+
+   /*
+* Having a mode that starts by a letter (and thus is named)
+* and an at-sign (used to specify a refresh rate) is
+* disallowed.
+*/
+   if (ret && refresh_ptr)
+   return false;
}
 
/* No named mode? Check for a normal mode argument, e.g. 1024x768 */

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 15/41] drm/modes: Switch to named mode descriptors

2022-08-29 Thread Maxime Ripard
The current named mode parsing relies only the mode name, and doesn't allow
to specify any other parameter.

Let's convert that string list to an array of a custom structure that will
hold the name and some additional parameters in the future.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 0636cb707544..1fdfa004b139 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2206,9 +2206,13 @@ static int drm_mode_parse_cmdline_options(const char 
*str,
return 0;
 }
 
-static const char * const drm_named_modes_whitelist[] = {
-   "NTSC",
-   "PAL",
+struct drm_named_mode {
+   const char *name;
+};
+
+static const struct drm_named_mode drm_named_modes[] = {
+   { "NTSC", },
+   { "PAL", },
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2241,14 +2245,15 @@ static int drm_mode_parse_cmdline_named_mode(const char 
*name,
 * We're sure we're a named mode at that point, iterate over the
 * list of modes we're aware of.
 */
-   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+   for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
+   const struct drm_named_mode *mode = &drm_named_modes[i];
int ret;
 
-   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+   ret = str_has_prefix(name, mode->name);
if (ret != name_end)
continue;
 
-   strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
+   strcpy(cmdline_mode->name, mode->name);
cmdline_mode->specified = true;
 
return 1;

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 21/41] drm/modes: Introduce more named modes

2022-08-29 Thread Maxime Ripard
Now that we can easily extend the named modes list, let's add a few more
analog TV modes that were used in the wild, and some unit tests to make
sure it works as intended.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 065dbfbd815e..7d769de4d31b 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2254,7 +2254,9 @@ struct drm_named_mode {
 
 static const struct drm_named_mode drm_named_modes[] = {
NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_NTSC_M),
+   NAMED_MODE("NTSC_J", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_NTSC_J),
NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_PAL_B),
+   NAMED_MODE("PAL_M", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_PAL_M),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c 
b/drivers/gpu/drm/tests/drm_client_modeset_test.c
index 4380cf670fb4..d6ecb5fbe159 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -140,6 +140,32 @@ static void drm_pick_cmdline_named_ntsc(struct kunit *test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
 }
 
+static void drm_pick_cmdline_named_ntsc_j(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv = test->priv;
+   struct drm_device *drm = priv->drm;
+   struct drm_connector *connector = &priv->connector;
+   struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+   struct drm_display_mode *mode;
+   const char *cmdline = "NTSC_J";
+   int ret;
+
+   KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+   connector,
+   
cmdline_mode));
+
+   mutex_lock(&drm->mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(&drm->mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
+}
+
 static void drm_pick_cmdline_named_pal(struct kunit *test)
 {
struct drm_client_modeset_test_priv *priv = test->priv;
@@ -166,10 +192,38 @@ static void drm_pick_cmdline_named_pal(struct kunit *test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_pal_576i(drm), 
mode));
 }
 
+static void drm_pick_cmdline_named_pal_m(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv = test->priv;
+   struct drm_device *drm = priv->drm;
+   struct drm_connector *connector = &priv->connector;
+   struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+   struct drm_display_mode *mode;
+   const char *cmdline = "PAL_M";
+   int ret;
+
+   KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+   connector,
+   
cmdline_mode));
+
+   mutex_lock(&drm->mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(&drm->mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
+}
+
 static struct kunit_case drm_pick_cmdline_tests[] = {
KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
KUNIT_CASE(drm_pick_cmdline_named_ntsc),
+   KUNIT_CASE(drm_pick_cmdline_named_ntsc_j),
KUNIT_CASE(drm_pick_cmdline_named_pal),
+   KUNIT_CASE(drm_pick_cmdline_named_pal_m),
{}
 };
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 18/41] drm/connector: Add a function to lookup a TV mode by its name

2022-08-29 Thread Maxime Ripard
As part of the command line parsing rework coming in the next patches,
we'll need to lookup drm_connector_tv_mode values by their name, already
defined in drm_tv_mode_enum_list.

In order to avoid any code duplication, let's do a function that will
perform a lookup of a TV mode name and return its value.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b1fcacd150e8..0fe01a1c20ad 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1003,6 +1003,30 @@ static const struct drm_prop_enum_list 
drm_tv_mode_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
 
+/**
+ * drm_get_tv_mode_from_name - Translates a TV mode name into its enum value
+ * @name: TV Mode name we want to convert
+ * @len: Length of @name
+ *
+ * Translates @name into an enum drm_connector_tv_mode.
+ *
+ * Returns: the enum value on success, a negative errno otherwise.
+ */
+int drm_get_tv_mode_from_name(const char *name, size_t len)
+{
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(drm_tv_mode_enum_list); i++) {
+   const struct drm_prop_enum_list *item = 
&drm_tv_mode_enum_list[i];
+
+   if (strlen(item->name) == len && !strncmp(item->name, name, 
len))
+   return item->type;
+   }
+
+   return -EINVAL;
+}
+EXPORT_SYMBOL(drm_get_tv_mode_from_name)
+
 static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index bb39d2bb806e..49d261977d4e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1943,6 +1943,8 @@ const char *drm_get_dp_subconnector_name(int val);
 const char *drm_get_content_protection_name(int val);
 const char *drm_get_hdcp_content_type_name(int val);
 
+int drm_get_tv_mode_from_name(const char *name, size_t len);
+
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 void drm_connector_attach_dp_subconnector_property(struct drm_connector 
*connector);
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 19/41] drm/modes: Introduce the tv_mode property as a command-line option

2022-08-29 Thread Maxime Ripard
Our new tv mode option allows to specify the TV mode from a property.
However, it can still be useful, for example to avoid any boot time
artifact, to set that property directly from the kernel command line.

Let's add some code to allow it, and some unit tests to exercise that code.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 73d01e755496..a759a4ba0036 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2115,6 +2115,30 @@ static int drm_mode_parse_panel_orientation(const char 
*delim,
return 0;
 }
 
+static int drm_mode_parse_tv_mode(const char *delim,
+ struct drm_cmdline_mode *mode)
+{
+   const char *value;
+   unsigned int len;
+   int ret;
+
+   if (*delim != '=')
+   return -EINVAL;
+
+   value = delim + 1;
+   delim = strchr(value, ',');
+   if (!delim)
+   delim = value + strlen(value);
+
+   ret = drm_get_tv_mode_from_name(value, delim - value);
+   if (ret < 0)
+   return ret;
+
+   mode->tv_mode = ret;
+
+   return 0;
+}
+
 static int drm_mode_parse_cmdline_options(const char *str,
  bool freestanding,
  const struct drm_connector *connector,
@@ -2184,6 +2208,9 @@ static int drm_mode_parse_cmdline_options(const char *str,
} else if (!strncmp(option, "panel_orientation", delim - 
option)) {
if (drm_mode_parse_panel_orientation(delim, mode))
return -EINVAL;
+   } else if (!strncmp(option, "tv_mode", delim - option)) {
+   if (drm_mode_parse_tv_mode(delim, mode))
+   return -EINVAL;
} else {
return -EINVAL;
}
@@ -2212,20 +2239,22 @@ struct drm_named_mode {
unsigned int xres;
unsigned int yres;
unsigned int flags;
+   unsigned int tv_mode;
 };
 
-#define NAMED_MODE(_name, _pclk, _x, _y, _flags)   \
+#define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode)\
{   \
.name = _name,  \
.pixel_clock_khz = _pclk,   \
.xres = _x, \
.yres = _y, \
.flags = _flags,\
+   .tv_mode = _mode,   \
}
 
 static const struct drm_named_mode drm_named_modes[] = {
-   NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
-   NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
+   NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_NTSC_M),
+   NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_PAL_B),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2271,6 +2300,7 @@ static int drm_mode_parse_cmdline_named_mode(const char 
*name,
cmdline_mode->xres = mode->xres;
cmdline_mode->yres = mode->yres;
cmdline_mode->interlace = !!(mode->flags & 
DRM_MODE_FLAG_INTERLACE);
+   cmdline_mode->tv_mode = mode->tv_mode;
cmdline_mode->specified = true;
 
return 1;
diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c 
b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
index 59b29cdfdd35..f1e73ed65be0 100644
--- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
+++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
@@ -885,6 +885,201 @@ static void drm_cmdline_test_multiple_options(struct 
kunit *test)
KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
 }
 
+static void drm_cmdline_test_tv_options(struct kunit *test,
+   const char *cmdline,
+   const struct drm_display_mode 
*expected_mode,
+   unsigned int expected_tv_mode)
+{
+   struct drm_cmdline_mode mode = { };
+
+   KUNIT_EXPECT_TRUE(test, 
drm_mode_parse_command_line_for_connector(cmdline,
+ 
&no_connector, &mode));
+   KUNIT_EXPECT_TRUE(test, mode.specified);
+   KUNIT_EXPECT_EQ(test, mode.xres, expected_mode->hdisplay);
+   KUNIT_EXPECT_EQ(test, mode.yres, expected_mode->vdisplay);
+   KUNIT_EXPECT_EQ(test, mode.tv_mode, expected_tv_mode);
+
+   KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+   KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+   KUNIT_EXPECT_FALSE(test, mode.rb);
+   KUNIT_EXPECT_FALSE(test, mode.cvt);
+   KUNIT_EXPECT_EQ(test, mode.interlace, !!(expected_mode->flags & 
DRM_MODE_FLAG_INTERLACE));
+   KUNIT_EXPECT_FALSE(t

[PATCH v2 16/41] drm/modes: Fill drm_cmdline mode from named modes

2022-08-29 Thread Maxime Ripard
The current code to deal with named modes will only set the mode name, and
then it's up to drivers to try to match that name to whatever mode or
configuration they see fit.

The plan is to remove that need and move the named mode handling out of
drivers and into the core, and only rely on modes and properties. Let's
start by properly filling drm_cmdline_mode from a named mode.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 1fdfa004b139..5e898699b532 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2208,11 +2208,22 @@ static int drm_mode_parse_cmdline_options(const char 
*str,
 
 struct drm_named_mode {
const char *name;
+   unsigned int xres;
+   unsigned int yres;
+   unsigned int flags;
 };
 
+#define NAMED_MODE(_name, _x, _y, _flags)  \
+   {   \
+   .name = _name,  \
+   .xres = _x, \
+   .yres = _y, \
+   .flags = _flags,\
+   }
+
 static const struct drm_named_mode drm_named_modes[] = {
-   { "NTSC", },
-   { "PAL", },
+   NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
+   NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2254,6 +2265,9 @@ static int drm_mode_parse_cmdline_named_mode(const char 
*name,
continue;
 
strcpy(cmdline_mode->name, mode->name);
+   cmdline_mode->xres = mode->xres;
+   cmdline_mode->yres = mode->yres;
+   cmdline_mode->interlace = !!(mode->flags & 
DRM_MODE_FLAG_INTERLACE);
cmdline_mode->specified = true;
 
return 1;

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 22/41] drm/atomic-helper: Add a TV properties reset helper

2022-08-29 Thread Maxime Ripard
The drm_tv_create_properties() function will create a bunch of properties,
but it's up to each and every driver using that function to properly reset
the state of these properties leading to inconsistent behaviours.

Let's create a helper that will take care of it.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index dfb57217253b..0373c3dc824b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -481,6 +481,81 @@ void drm_atomic_helper_connector_tv_margins_reset(struct 
drm_connector *connecto
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
 
+/**
+ * drm_atomic_helper_connector_tv_reset - Resets Analog TV connector properties
+ * @connector: DRM connector
+ *
+ * Resets the analog TV properties attached to a connector
+ */
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
+{
+   struct drm_device *dev = connector->dev;
+   struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
+   struct drm_connector_state *state = connector->state;
+   struct drm_property *prop;
+   uint64_t val;
+
+   prop = dev->mode_config.tv_mode_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.mode = val;
+
+   if (cmdline->tv_mode)
+   state->tv.mode = cmdline->tv_mode;
+
+   prop = dev->mode_config.tv_select_subconnector_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.select_subconnector = val;
+
+   prop = dev->mode_config.tv_subconnector_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.subconnector = val;
+
+   prop = dev->mode_config.tv_brightness_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.brightness = val;
+
+   prop = dev->mode_config.tv_contrast_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.contrast = val;
+
+   prop = dev->mode_config.tv_flicker_reduction_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.flicker_reduction = val;
+
+   prop = dev->mode_config.tv_overscan_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.overscan = val;
+
+   prop = dev->mode_config.tv_saturation_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.saturation = val;
+
+   prop = dev->mode_config.tv_hue_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(&connector->base,
+  prop, &val))
+   state->tv.hue = val;
+
+   drm_atomic_helper_connector_tv_margins_reset(connector);
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
diff --git a/include/drm/drm_atomic_state_helper.h 
b/include/drm/drm_atomic_state_helper.h
index 192766656b88..c8fbce795ee7 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -70,6 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct 
drm_connector_state *conn_
 void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
 struct drm_connector_state 
*conn_state);
 void drm_atomic_helper_connector_reset(struct drm_connector *connector);
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
 void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector 
*connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 26/41] drm/vc4: vec: Refactor VEC TV mode setting

2022-08-29 Thread Maxime Ripard
From: Mateusz Kwiatkowski 

Change the mode_set function pointer logic to declarative config0,
config1 and custom_freq fields, to make TV mode setting logic more
concise and uniform.

Signed-off-by: Mateusz Kwiatkowski 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 72eee0cbb615..9a37c3fcc295 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -194,7 +194,9 @@ enum vc4_vec_tv_mode_id {
 
 struct vc4_vec_tv_mode {
const struct drm_display_mode *mode;
-   void (*mode_set)(struct vc4_vec *vec);
+   u32 config0;
+   u32 config1;
+   u32 custom_freq;
 };
 
 static const struct debugfs_reg32 vec_regs[] = {
@@ -224,34 +226,6 @@ static const struct debugfs_reg32 vec_regs[] = {
VC4_REG32(VEC_DAC_MISC),
 };
 
-static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
-{
-   struct drm_device *drm = vec->connector.dev;
-   int idx;
-
-   if (!drm_dev_enter(drm, &idx))
-   return;
-
-   VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
-   VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
-
-   drm_dev_exit(idx);
-}
-
-static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
-{
-   struct drm_device *drm = vec->connector.dev;
-   int idx;
-
-   if (!drm_dev_enter(drm, &idx))
-   return;
-
-   VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
-   VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
-
-   drm_dev_exit(idx);
-}
-
 static const struct drm_display_mode ntsc_mode = {
DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
@@ -259,37 +233,6 @@ static const struct drm_display_mode ntsc_mode = {
 DRM_MODE_FLAG_INTERLACE)
 };
 
-static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
-{
-   struct drm_device *drm = vec->connector.dev;
-   int idx;
-
-   if (!drm_dev_enter(drm, &idx))
-   return;
-
-   VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
-   VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
-
-   drm_dev_exit(idx);
-}
-
-static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
-{
-   struct drm_device *drm = vec->connector.dev;
-   int idx;
-
-   if (!drm_dev_enter(drm, &idx))
-   return;
-
-   VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
-   VEC_WRITE(VEC_CONFIG1,
- VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
-   VEC_WRITE(VEC_FREQ3_2, 0x223b);
-   VEC_WRITE(VEC_FREQ1_0, 0x61d1);
-
-   drm_dev_exit(idx);
-}
-
 static const struct drm_display_mode pal_mode = {
DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
@@ -300,19 +243,24 @@ static const struct drm_display_mode pal_mode = {
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
[VC4_VEC_TV_MODE_NTSC] = {
.mode = &ntsc_mode,
-   .mode_set = vc4_vec_ntsc_mode_set,
+   .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_J] = {
.mode = &ntsc_mode,
-   .mode_set = vc4_vec_ntsc_j_mode_set,
+   .config0 = VEC_CONFIG0_NTSC_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL] = {
.mode = &pal_mode,
-   .mode_set = vc4_vec_pal_mode_set,
+   .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
.mode = &pal_mode,
-   .mode_set = vc4_vec_pal_m_mode_set,
+   .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x223b61d1,
},
 };
 
@@ -470,7 +418,16 @@ static void vc4_vec_encoder_enable(struct drm_encoder 
*encoder,
/* Mask all interrupts. */
VEC_WRITE(VEC_MASK0, 0);
 
-   vec->tv_mode->mode_set(vec);
+   VEC_WRITE(VEC_CONFIG0, vec->tv_mode->config0);
+   VEC_WRITE(VEC_CONFIG1, vec->tv_mode->config1);
+
+   if (vec->tv_mode->custom_freq != 0) {
+   VEC_WRITE(VEC_FREQ3_2,
+ (vec->tv_mode->custom_freq >> 16) &
+ 0x);
+   VEC_WRITE(VEC_FREQ1_0,
+ vec->tv_mode->custom_freq & 0x);
+   }
 
VEC_WRITE(VEC_DAC_MISC,
  VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 28/41] drm/vc4: vec: Fix timings for VEC modes

2022-08-29 Thread Maxime Ripard
From: Mateusz Kwiatkowski 

This commit fixes vertical timings of the VEC (composite output) modes
to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R
standards.

Previous timings were actually defined as 502 and 601 lines, resulting
in non-standard 62.69 Hz and 52 Hz signals being generated,
respectively.

Signed-off-by: Mateusz Kwiatkowski 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 4d7bc7c20704..d1d40b69279e 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -227,14 +227,14 @@ static const struct debugfs_reg32 vec_regs[] = {
 static const struct drm_display_mode ntsc_mode = {
DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
-480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
+480, 480 + 7, 480 + 7 + 6, 525, 0,
 DRM_MODE_FLAG_INTERLACE)
 };
 
 static const struct drm_display_mode pal_mode = {
DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
-576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
+576, 576 + 4, 576 + 4 + 6, 625, 0,
 DRM_MODE_FLAG_INTERLACE)
 };
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 30/41] drm/vc4: vec: Fix definition of PAL-M mode

2022-08-29 Thread Maxime Ripard
From: Mateusz Kwiatkowski 

PAL-M is a Brazilian analog TV standard that uses a PAL-style chroma
subcarrier at 3.575611[888111] MHz on top of 525-line (480i60) timings.
This commit makes the driver actually use the proper VEC preset for this
mode instead of just changing PAL subcarrier frequency.

Signed-off-by: Mateusz Kwiatkowski 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 63e4e617e321..fa85dd260742 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -69,6 +69,7 @@
 #define VEC_CONFIG0_STD_MASK   GENMASK(1, 0)
 #define VEC_CONFIG0_NTSC_STD   0
 #define VEC_CONFIG0_PAL_BDGHI_STD  1
+#define VEC_CONFIG0_PAL_M_STD  2
 #define VEC_CONFIG0_PAL_N_STD  3
 
 #define VEC_SCHPH  0x108
@@ -241,10 +242,9 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
-   .mode = &drm_mode_576i,
-   .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
-   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
-   .custom_freq = 0x223b61d1,
+   .mode = &drm_mode_480i,
+   .config0 = VEC_CONFIG0_PAL_M_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
 };
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 25/41] drm/vc4: vec: Convert to atomic helpers

2022-08-29 Thread Maxime Ripard
The VC4 VEC driver still uses legacy enable and disable hook
implementation. Let's convert to the atomic variants.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index d521ffd8d75c..72eee0cbb615 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -375,7 +375,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, 
struct vc4_vec *vec)
return 0;
 }
 
-static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
+static void vc4_vec_encoder_disable(struct drm_encoder *encoder,
+   struct drm_atomic_state *state)
 {
struct drm_device *drm = encoder->dev;
struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
@@ -406,7 +407,8 @@ static void vc4_vec_encoder_disable(struct drm_encoder 
*encoder)
drm_dev_exit(idx);
 }
 
-static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
+static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
+  struct drm_atomic_state *state)
 {
struct drm_device *drm = encoder->dev;
struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
@@ -508,9 +510,9 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
 }
 
 static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
-   .disable = vc4_vec_encoder_disable,
-   .enable = vc4_vec_encoder_enable,
.atomic_check = vc4_vec_encoder_atomic_check,
+   .atomic_disable = vc4_vec_encoder_disable,
+   .atomic_enable = vc4_vec_encoder_enable,
.atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 };
 

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 23/41] drm/atomic-helper: Add an analog TV atomic_check implementation

2022-08-29 Thread Maxime Ripard
The analog TV connector drivers share some atomic_check logic, and the new
TV standard property have created a bunch of new constraints that needs to
be shared across drivers too.

Let's create an atomic_check helper for those use cases.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 0373c3dc824b..d64733c6aae3 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -556,6 +556,42 @@ void drm_atomic_helper_connector_tv_reset(struct 
drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
 
+/**
+ * @drm_atomic_helper_connector_tv_check: Validate an analog TV connector state
+ * @connector: DRM Connector
+ * @state: the DRM State object
+ *
+ * Checks the state object to see if the requested state is valid for an
+ * analog TV connector.
+ *
+ * Returns:
+ * Zero for success, a negative error code on error.
+ */
+int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
+struct drm_atomic_state *state)
+{
+   struct drm_connector_state *old_conn_state =
+   drm_atomic_get_old_connector_state(state, connector);
+   struct drm_connector_state *new_conn_state =
+   drm_atomic_get_new_connector_state(state, connector);
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+
+   crtc = new_conn_state->crtc;
+   if (!crtc)
+   return 0;
+
+   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+   if (!crtc_state)
+   return -EINVAL;
+
+   if (old_conn_state->tv.mode != new_conn_state->tv.mode)
+   crtc_state->mode_changed = true;
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
+
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
diff --git a/include/drm/drm_atomic_state_helper.h 
b/include/drm/drm_atomic_state_helper.h
index c8fbce795ee7..b9740edb2658 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -26,6 +26,7 @@
 
 #include 
 
+struct drm_atomic_state;
 struct drm_bridge;
 struct drm_bridge_state;
 struct drm_crtc;
@@ -71,6 +72,8 @@ void __drm_atomic_helper_connector_reset(struct drm_connector 
*connector,
 struct drm_connector_state 
*conn_state);
 void drm_atomic_helper_connector_reset(struct drm_connector *connector);
 void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
+struct drm_atomic_state *state);
 void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector 
*connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 24/41] drm/vc4: vec: Remove empty mode_fixup

2022-08-29 Thread Maxime Ripard
The mode_fixup hooks are deprecated, and the behaviour we implement is the
default one anyway. Let's remove it.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index d5140fe0be4f..d521ffd8d75c 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -483,14 +483,6 @@ static void vc4_vec_encoder_enable(struct drm_encoder 
*encoder)
drm_dev_exit(idx);
 }
 
-
-static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
-  const struct drm_display_mode *mode,
-  struct drm_display_mode *adjusted_mode)
-{
-   return true;
-}
-
 static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@@ -518,7 +510,6 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
 static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
.disable = vc4_vec_encoder_disable,
.enable = vc4_vec_encoder_enable,
-   .mode_fixup = vc4_vec_encoder_mode_fixup,
.atomic_check = vc4_vec_encoder_atomic_check,
.atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 };

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 20/41] drm/modes: Properly generate a drm_display_mode from a named mode

2022-08-29 Thread Maxime Ripard
The framework will get the drm_display_mode from the drm_cmdline_mode it
got by parsing the video command line argument by calling
drm_connector_pick_cmdline_mode().

The heavy lifting will then be done by the drm_mode_create_from_cmdline_mode()
function.

In the case of the named modes though, there's no real code to make that
translation and we rely on the drivers to guess which actual display mode
we meant.

Let's modify drm_mode_create_from_cmdline_mode() to properly generate the
drm_display_mode we mean when passing a named mode.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index a759a4ba0036..065dbfbd815e 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2480,6 +2480,36 @@ bool drm_mode_parse_command_line_for_connector(const 
char *mode_option,
 }
 EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
 
+static struct drm_display_mode *drm_named_mode(struct drm_device *dev,
+  struct drm_cmdline_mode *cmd)
+{
+   struct drm_display_mode *mode;
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
+   const struct drm_named_mode *named_mode = &drm_named_modes[i];
+
+   if (strcmp(cmd->name, named_mode->name))
+   continue;
+
+   if (!named_mode->tv_mode)
+   continue;
+
+   mode = drm_analog_tv_mode(dev,
+ named_mode->tv_mode,
+ named_mode->pixel_clock_khz * 1000,
+ named_mode->xres,
+ named_mode->yres,
+ named_mode->flags & 
DRM_MODE_FLAG_INTERLACE);
+   if (!mode)
+   return NULL;
+
+   return mode;
+   }
+
+   return NULL;
+}
+
 /**
  * drm_mode_create_from_cmdline_mode - convert a command line modeline into a 
DRM display mode
  * @dev: DRM device to create the new mode for
@@ -2497,7 +2527,9 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
if (cmd->xres == 0 || cmd->yres == 0)
return NULL;
 
-   if (cmd->cvt)
+   if (strlen(cmd->name))
+   mode = drm_named_mode(dev, cmd);
+   else if (cmd->cvt)
mode = drm_cvt_mode(dev,
cmd->xres, cmd->yres,
cmd->refresh_specified ? cmd->refresh : 60,
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c 
b/drivers/gpu/drm/tests/drm_client_modeset_test.c
index 46335de7bc6b..4380cf670fb4 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -26,6 +26,20 @@ static int drm_client_modeset_connector_get_modes(struct 
drm_connector *connecto
 
count = drm_add_modes_noedid(connector, 1920, 1200);
 
+   mode = drm_mode_analog_ntsc_480i(connector->dev);
+   if (!mode)
+   return -ENOMEM;
+
+   drm_mode_probed_add(connector, mode);
+   count += 1;
+
+   mode = drm_mode_analog_pal_576i(connector->dev);
+   if (!mode)
+   return -ENOMEM;
+
+   drm_mode_probed_add(connector, mode);
+   count += 1;
+
return count;
 }
 
@@ -58,6 +72,9 @@ static int drm_client_modeset_test_init(struct kunit *test)
return ret;
drm_connector_helper_add(&priv->connector, 
&drm_client_modeset_connector_helper_funcs);
 
+   priv->connector.interlace_allowed = true;
+   priv->connector.doublescan_allowed = true;
+
return 0;
 }
 
@@ -97,8 +114,62 @@ static void drm_pick_cmdline_res_1920_1080_60(struct kunit 
*test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
 }
 
+static void drm_pick_cmdline_named_ntsc(struct kunit *test)
+{
+   struct drm_client_modeset_test_priv *priv = test->priv;
+   struct drm_device *drm = priv->drm;
+   struct drm_connector *connector = &priv->connector;
+   struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+   struct drm_display_mode *mode;
+   const char *cmdline = "NTSC";
+   int ret;
+
+   KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+   connector,
+   
cmdline_mode));
+
+   mutex_lock(&drm->mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(&drm->mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
+}
+
+static void drm_pick

[PATCH v2 27/41] drm/vc4: vec: Remove redundant atomic_mode_set

2022-08-29 Thread Maxime Ripard
From: Mateusz Kwiatkowski 

Let's remove the superfluous tv_mode field, which was redundant with the
mode field in struct drm_tv_connector_state.

Signed-off-by: Mateusz Kwiatkowski 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 9a37c3fcc295..4d7bc7c20704 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -171,8 +171,6 @@ struct vc4_vec {
 
struct clk *clock;
 
-   const struct vc4_vec_tv_mode *tv_mode;
-
struct debugfs_regset32 regset;
 };
 
@@ -316,7 +314,6 @@ static int vc4_vec_connector_init(struct drm_device *dev, 
struct vc4_vec *vec)
drm_object_attach_property(&connector->base,
   dev->mode_config.legacy_tv_mode_property,
   VC4_VEC_TV_MODE_NTSC);
-   vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
 
drm_connector_attach_encoder(connector, &vec->encoder.base);
 
@@ -360,6 +357,11 @@ static void vc4_vec_encoder_enable(struct drm_encoder 
*encoder,
 {
struct drm_device *drm = encoder->dev;
struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
+   struct drm_connector *connector = &vec->connector;
+   struct drm_connector_state *conn_state =
+   drm_atomic_get_new_connector_state(state, connector);
+   const struct vc4_vec_tv_mode *tv_mode =
+   &vc4_vec_tv_modes[conn_state->tv.mode];
int idx, ret;
 
if (!drm_dev_enter(drm, &idx))
@@ -418,15 +420,14 @@ static void vc4_vec_encoder_enable(struct drm_encoder 
*encoder,
/* Mask all interrupts. */
VEC_WRITE(VEC_MASK0, 0);
 
-   VEC_WRITE(VEC_CONFIG0, vec->tv_mode->config0);
-   VEC_WRITE(VEC_CONFIG1, vec->tv_mode->config1);
+   VEC_WRITE(VEC_CONFIG0, tv_mode->config0);
+   VEC_WRITE(VEC_CONFIG1, tv_mode->config1);
 
-   if (vec->tv_mode->custom_freq != 0) {
+   if (tv_mode->custom_freq != 0) {
VEC_WRITE(VEC_FREQ3_2,
- (vec->tv_mode->custom_freq >> 16) &
- 0x);
+ (tv_mode->custom_freq >> 16) & 0x);
VEC_WRITE(VEC_FREQ1_0,
- vec->tv_mode->custom_freq & 0x);
+ tv_mode->custom_freq & 0x);
}
 
VEC_WRITE(VEC_DAC_MISC,
@@ -442,15 +443,6 @@ static void vc4_vec_encoder_enable(struct drm_encoder 
*encoder,
drm_dev_exit(idx);
 }
 
-static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
-   struct drm_crtc_state *crtc_state,
-   struct drm_connector_state *conn_state)
-{
-   struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
-
-   vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
-}
-
 static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@@ -470,7 +462,6 @@ static const struct drm_encoder_helper_funcs 
vc4_vec_encoder_helper_funcs = {
.atomic_check = vc4_vec_encoder_atomic_check,
.atomic_disable = vc4_vec_encoder_disable,
.atomic_enable = vc4_vec_encoder_enable,
-   .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 };
 
 static int vc4_vec_late_register(struct drm_encoder *encoder)

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 29/41] drm/vc4: vec: Switch for common modes

2022-08-29 Thread Maxime Ripard
Now that the core has a definition for the 525 and 625 lines analog TV
modes, let's switch to it for vc4.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index d1d40b69279e..63e4e617e321 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -224,38 +224,24 @@ static const struct debugfs_reg32 vec_regs[] = {
VC4_REG32(VEC_DAC_MISC),
 };
 
-static const struct drm_display_mode ntsc_mode = {
-   DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
-720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
-480, 480 + 7, 480 + 7 + 6, 525, 0,
-DRM_MODE_FLAG_INTERLACE)
-};
-
-static const struct drm_display_mode pal_mode = {
-   DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
-720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
-576, 576 + 4, 576 + 4 + 6, 625, 0,
-DRM_MODE_FLAG_INTERLACE)
-};
-
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
[VC4_VEC_TV_MODE_NTSC] = {
-   .mode = &ntsc_mode,
+   .mode = &drm_mode_480i,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_J] = {
-   .mode = &ntsc_mode,
+   .mode = &drm_mode_480i,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL] = {
-   .mode = &pal_mode,
+   .mode = &drm_mode_576i,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
-   .mode = &pal_mode,
+   .mode = &drm_mode_576i,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
.custom_freq = 0x223b61d1,

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 17/41] drm/connector: Add pixel clock to cmdline mode

2022-08-29 Thread Maxime Ripard
We'll need to get the pixel clock to generate proper display modes for
all the current named modes. Let's add it to struct drm_cmdline_mode and
fill it when parsing the named mode.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5e898699b532..73d01e755496 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2208,22 +2208,24 @@ static int drm_mode_parse_cmdline_options(const char 
*str,
 
 struct drm_named_mode {
const char *name;
+   unsigned int pixel_clock_khz;
unsigned int xres;
unsigned int yres;
unsigned int flags;
 };
 
-#define NAMED_MODE(_name, _x, _y, _flags)  \
+#define NAMED_MODE(_name, _pclk, _x, _y, _flags)   \
{   \
.name = _name,  \
+   .pixel_clock_khz = _pclk,   \
.xres = _x, \
.yres = _y, \
.flags = _flags,\
}
 
 static const struct drm_named_mode drm_named_modes[] = {
-   NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
-   NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
+   NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
+   NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2265,6 +2267,7 @@ static int drm_mode_parse_cmdline_named_mode(const char 
*name,
continue;
 
strcpy(cmdline_mode->name, mode->name);
+   cmdline_mode->pixel_clock = mode->pixel_clock_khz;
cmdline_mode->xres = mode->xres;
cmdline_mode->yres = mode->yres;
cmdline_mode->interlace = !!(mode->flags & 
DRM_MODE_FLAG_INTERLACE);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 7d3881f35e7c..bb39d2bb806e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1352,6 +1352,13 @@ struct drm_cmdline_mode {
 */
bool bpp_specified;
 
+   /**
+* @pixel_clock:
+*
+* Pixel Clock in kHz. Optional.
+*/
+   unsigned int pixel_clock;
+
/**
 * @xres:
 *

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 41/41] drm/sun4i: tv: Convert to the new TV mode property

2022-08-29 Thread Maxime Ripard
Now that the core can deal fine with analog TV modes, let's convert the
sun4i TV driver to leverage those new features.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 74ff5ad6a8b9..10c0d727d700 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -140,23 +140,14 @@ struct resync_parameters {
 struct tv_mode {
char*name;
 
+   unsigned inttv_mode;
+
u32 mode;
u32 chroma_freq;
u16 back_porch;
u16 front_porch;
-   u16 line_number;
u16 vblank_level;
 
-   u32 hdisplay;
-   u16 hfront_porch;
-   u16 hsync_len;
-   u16 hback_porch;
-
-   u32 vdisplay;
-   u16 vfront_porch;
-   u16 vsync_len;
-   u16 vback_porch;
-
boolyc_en;
booldac3_en;
booldac_bit25_en;
@@ -212,7 +203,7 @@ static const struct resync_parameters pal_resync_parameters 
= {
 
 static const struct tv_mode tv_modes[] = {
{
-   .name   = "NTSC",
+   .tv_mode= DRM_MODE_TV_MODE_NTSC_M,
.mode   = SUN4I_TVE_CFG0_RES_480i,
.chroma_freq= 0x21f07c1f,
.yc_en  = true,
@@ -221,17 +212,6 @@ static const struct tv_mode tv_modes[] = {
 
.back_porch = 118,
.front_porch= 32,
-   .line_number= 525,
-
-   .hdisplay   = 720,
-   .hfront_porch   = 18,
-   .hsync_len  = 2,
-   .hback_porch= 118,
-
-   .vdisplay   = 480,
-   .vfront_porch   = 26,
-   .vsync_len  = 2,
-   .vback_porch= 17,
 
.vblank_level   = 240,
 
@@ -241,23 +221,12 @@ static const struct tv_mode tv_modes[] = {
.resync_params  = &ntsc_resync_parameters,
},
{
-   .name   = "PAL",
+   .tv_mode= DRM_MODE_TV_MODE_PAL_B,
.mode   = SUN4I_TVE_CFG0_RES_576i,
.chroma_freq= 0x2a098acb,
 
.back_porch = 138,
.front_porch= 24,
-   .line_number= 625,
-
-   .hdisplay   = 720,
-   .hfront_porch   = 3,
-   .hsync_len  = 2,
-   .hback_porch= 139,
-
-   .vdisplay   = 576,
-   .vfront_porch   = 28,
-   .vsync_len  = 2,
-   .vback_porch= 19,
 
.vblank_level   = 252,
 
@@ -275,63 +244,21 @@ drm_encoder_to_sun4i_tv(struct drm_encoder *encoder)
encoder);
 }
 
-/*
- * FIXME: If only the drm_display_mode private field was usable, this
- * could go away...
- *
- * So far, it doesn't seem to be preserved when the mode is passed by
- * to mode_set for some reason.
- */
-static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct 
drm_display_mode *mode)
+static const struct tv_mode *
+sun4i_tv_find_tv_by_mode(unsigned int mode)
 {
int i;
 
-   /* First try to identify the mode by name */
for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
const struct tv_mode *tv_mode = &tv_modes[i];
 
-   DRM_DEBUG_DRIVER("Comparing mode %s vs %s",
-mode->name, tv_mode->name);
-
-   if (!strcmp(mode->name, tv_mode->name))
-   return tv_mode;
-   }
-
-   /* Then by number of lines */
-   for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
-   const struct tv_mode *tv_mode = &tv_modes[i];
-
-   DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)",
-mode->name, tv_mode->name,
-mode->vdisplay, tv_mode->vdisplay);
-
-   if (mode->vdisplay == tv_mode->vdisplay)
+   if (tv_mode->tv_mode == mode)
return tv_mode;
}
 
return NULL;
 }
 
-static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode,
- struct drm_display_mode *mode)
-{
-   DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name);
-
-   mode->type = DRM_MODE_TYPE_DRIVER;
-   mode->clock = 13500;
-   mode->flags = DRM_MODE_FLAG_INTERLACE;
-
-   mode->hdisplay = tv_mode->hdisplay;
-   mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch;
-   mode->hsync_end = mode->hsync_start + tv_mode->hsync_len;
-   mode->htotal = mode->hsync_end  + tv_mode->hback_porch;
-
-   mode->vdisplay = tv_mode->vdisplay;
-   mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch;
-   mode->vsync_end 

[PATCH v2 31/41] drm/vc4: vec: Use TV Reset implementation

2022-08-29 Thread Maxime Ripard
The analog TV properties created by the drm_mode_create_tv_properties() are
not properly initialised at reset. Let's switch our implementation to call
drm_atomic_helper_connector_tv_reset().

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index fa85dd260742..ba6f81908923 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -254,6 +254,12 @@ vc4_vec_connector_detect(struct drm_connector *connector, 
bool force)
return connector_status_unknown;
 }
 
+static void vc4_vec_connector_reset(struct drm_connector *connector)
+{
+   drm_atomic_helper_connector_reset(connector);
+   drm_atomic_helper_connector_tv_reset(connector);
+}
+
 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 {
struct drm_connector_state *state = connector->state;
@@ -274,7 +280,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector 
*connector)
 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
.detect = vc4_vec_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
-   .reset = drm_atomic_helper_connector_reset,
+   .reset = vc4_vec_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 37/41] drm/sun4i: tv: Remove useless function

2022-08-29 Thread Maxime Ripard
The drm_connector_to_sun4i_tv() function isn't used anywhere in the driver,
so let's remove it.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 3944da9a3c34..52bbba8f19dc 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -275,13 +275,6 @@ drm_encoder_to_sun4i_tv(struct drm_encoder *encoder)
encoder);
 }
 
-static inline struct sun4i_tv *
-drm_connector_to_sun4i_tv(struct drm_connector *connector)
-{
-   return container_of(connector, struct sun4i_tv,
-   connector);
-}
-
 /*
  * FIXME: If only the drm_display_mode private field was usable, this
  * could go away...

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 36/41] drm/sun4i: tv: Merge mode_set into atomic_enable

2022-08-29 Thread Maxime Ripard
Our mode_set implementation can be merged into our atomic_enable
implementation to simplify things, so let's do this.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index f7aad995ab5b..3944da9a3c34 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -359,23 +359,13 @@ static void sun4i_tv_enable(struct drm_encoder *encoder,
 {
struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-
-   DRM_DEBUG_DRIVER("Enabling the TV Output\n");
-
-   sunxi_engine_apply_color_correction(crtc->engine);
-
-   regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
-  SUN4I_TVE_EN_ENABLE,
-  SUN4I_TVE_EN_ENABLE);
-}
-
-static void sun4i_tv_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
-   struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
+   struct drm_crtc_state *crtc_state =
+   drm_atomic_get_new_crtc_state(state, encoder->crtc);
+   struct drm_display_mode *mode = &crtc_state->mode;
const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
+   DRM_DEBUG_DRIVER("Enabling the TV Output\n");
+
/* Enable and map the DAC to the output */
regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
   SUN4I_TVE_EN_DAC_MAP_MASK,
@@ -468,12 +458,17 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
  SUN4I_TVE_RESYNC_FIELD : 0));
 
regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0);
+
+   sunxi_engine_apply_color_correction(crtc->engine);
+
+   regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
+  SUN4I_TVE_EN_ENABLE,
+  SUN4I_TVE_EN_ENABLE);
 }
 
 static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
.atomic_disable = sun4i_tv_disable,
.atomic_enable  = sun4i_tv_enable,
-   .mode_set   = sun4i_tv_mode_set,
 };
 
 static int sun4i_tv_comp_get_modes(struct drm_connector *connector)

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 32/41] drm/vc4: vec: Convert to the new TV mode property

2022-08-29 Thread Maxime Ripard
Now that the core can deal fine with analog TV modes, let's convert the vc4
VEC driver to leverage those new features.

We've added some backward compatibility to support the old TV mode property
and translate it into the new TV norm property.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index ba6f81908923..58286acf4b9e 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -172,6 +172,8 @@ struct vc4_vec {
 
struct clk *clock;
 
+   struct drm_property *legacy_tv_mode_property;
+
struct debugfs_regset32 regset;
 };
 
@@ -184,6 +186,12 @@ encoder_to_vc4_vec(struct drm_encoder *encoder)
return container_of(encoder, struct vc4_vec, encoder.base);
 }
 
+static inline struct vc4_vec *
+connector_to_vc4_vec(struct drm_connector *connector)
+{
+   return container_of(connector, struct vc4_vec, connector);
+}
+
 enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_NTSC,
VC4_VEC_TV_MODE_NTSC_J,
@@ -192,7 +200,7 @@ enum vc4_vec_tv_mode_id {
 };
 
 struct vc4_vec_tv_mode {
-   const struct drm_display_mode *mode;
+   unsigned int mode;
u32 config0;
u32 config1;
u32 custom_freq;
@@ -226,28 +234,50 @@ static const struct debugfs_reg32 vec_regs[] = {
 };
 
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
-   [VC4_VEC_TV_MODE_NTSC] = {
-   .mode = &drm_mode_480i,
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC_M,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_NTSC_J] = {
-   .mode = &drm_mode_480i,
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC_J,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_PAL] = {
-   .mode = &drm_mode_576i,
+   {
+   .mode = DRM_MODE_TV_MODE_PAL_B,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_PAL_M] = {
-   .mode = &drm_mode_480i,
+   {
+   .mode = DRM_MODE_TV_MODE_PAL_M,
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
 };
 
+static inline const struct vc4_vec_tv_mode *
+vc4_vec_tv_mode_lookup(unsigned int mode)
+{
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(vc4_vec_tv_modes); i++) {
+   const struct vc4_vec_tv_mode *tv_mode = &vc4_vec_tv_modes[i];
+
+   if (tv_mode->mode == mode)
+   return tv_mode;
+   }
+
+   return NULL;
+}
+
+static const struct drm_prop_enum_list tv_mode_names[] = {
+   { VC4_VEC_TV_MODE_NTSC, "NTSC", },
+   { VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", },
+   { VC4_VEC_TV_MODE_PAL, "PAL", },
+   { VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
+};
+
 static enum drm_connector_status
 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -262,19 +292,98 @@ static void vc4_vec_connector_reset(struct drm_connector 
*connector)
 
 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 {
-   struct drm_connector_state *state = connector->state;
struct drm_display_mode *mode;
+   int count = 0;
 
-   mode = drm_mode_duplicate(connector->dev,
- vc4_vec_tv_modes[state->tv.mode].mode);
+   mode = drm_mode_analog_ntsc_480i(connector->dev);
if (!mode) {
DRM_ERROR("Failed to create a new display mode\n");
return -ENOMEM;
}
 
drm_mode_probed_add(connector, mode);
+   count += 1;
 
-   return 1;
+   mode = drm_mode_analog_pal_576i(connector->dev);
+   if (!mode) {
+   DRM_ERROR("Failed to create a new display mode\n");
+   return -ENOMEM;
+   }
+
+   drm_mode_probed_add(connector, mode);
+   count += 1;
+
+   return count;
+}
+
+static int
+vc4_vec_connector_set_property(struct drm_connector *connector,
+  struct drm_connector_state *state,
+  struct drm_property *property,
+  uint64_t val)
+{
+   struct vc4_vec *vec = connector_to_vc4_vec(connector);
+
+   if (property != vec->legacy_tv_mode_property)
+   return -EINVAL;
+
+   switch (val) {
+   case VC4_VEC_TV_MODE_NTSC:
+   state->tv.mode = DRM_MODE_TV_MODE_NTSC_M;
+   break;
+
+   case VC4_VEC_TV_MODE_NTSC_J:
+   state->tv.mode = DRM_MODE_TV_MODE_NTSC_J;
+   break;
+
+   case VC4_VEC_TV_MODE_PAL:
+   state->tv.mode = DRM_MODE_TV_MODE_PAL_B;
+   break;
+
+   case VC4_VEC_TV_MODE_PAL_M:
+   state->tv.mode = DRM_MODE_TV_MODE_PAL_M;
+   

[PATCH v2 39/41] drm/sun4i: tv: Rename error label

2022-08-29 Thread Maxime Ripard
The other error labels in sun4i_tv_bind() are named after the task they
perform (err_disable_clk to call clk_disable_unprepare for example).

However, the err_cleanup_connector is named after the calling site
(drm_connector_init failing) and will actually cleanup the encoder. Let's
rename it to err_cleanup_encoder to be consistent.

Signed-off-by: Maxime Ripard 
Reviewed-by: Jernej Skrabec 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 6d7e1d51569a..ad6a3739bfa9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -580,7 +580,7 @@ static int sun4i_tv_bind(struct device *dev, struct device 
*master,
if (ret) {
dev_err(dev,
"Couldn't initialise the Composite connector\n");
-   goto err_cleanup_connector;
+   goto err_cleanup_encoder;
}
tv->connector.interlace_allowed = true;
 
@@ -588,7 +588,7 @@ static int sun4i_tv_bind(struct device *dev, struct device 
*master,
 
return 0;
 
-err_cleanup_connector:
+err_cleanup_encoder:
drm_encoder_cleanup(&tv->encoder);
 err_disable_clk:
clk_disable_unprepare(tv->clk);

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 34/41] drm/sun4i: tv: Remove unused mode_valid

2022-08-29 Thread Maxime Ripard
The mode_valid implementation is pretty much a nop, let's remove it.

Signed-off-by: Maxime Ripard 
Reviewed-by: Jernej Skrabec 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 94883abe0dfd..53152d77c392 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -497,16 +497,8 @@ static int sun4i_tv_comp_get_modes(struct drm_connector 
*connector)
return i;
 }
 
-static int sun4i_tv_comp_mode_valid(struct drm_connector *connector,
-   struct drm_display_mode *mode)
-{
-   /* TODO */
-   return MODE_OK;
-}
-
 static const struct drm_connector_helper_funcs 
sun4i_tv_comp_connector_helper_funcs = {
.get_modes  = sun4i_tv_comp_get_modes,
-   .mode_valid = sun4i_tv_comp_mode_valid,
 };
 
 static void

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 40/41] drm/sun4i: tv: Add missing reset assertion

2022-08-29 Thread Maxime Ripard
The reset line is deasserted at bind, and asserted if we ever encounter an
error there. However, it's never asserted in unbind which will lead to a
resource unbalance.

Signed-off-by: Maxime Ripard 
Reviewed-by: Jernej Skrabec 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index ad6a3739bfa9..74ff5ad6a8b9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -605,6 +605,7 @@ static void sun4i_tv_unbind(struct device *dev, struct 
device *master,
drm_connector_cleanup(&tv->connector);
drm_encoder_cleanup(&tv->encoder);
clk_disable_unprepare(tv->clk);
+   reset_control_assert(tv->reset);
 }
 
 static const struct component_ops sun4i_tv_ops = {

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 33/41] drm/vc4: vec: Add support for more analog TV standards

2022-08-29 Thread Maxime Ripard
From: Mateusz Kwiatkowski 

Add support for the following composite output modes (all of them are
somewhat more obscure than the previously defined ones):

- NTSC_443 - NTSC-style signal with the chroma subcarrier shifted to
  4.43361875 MHz (the PAL subcarrier frequency). Never used for
  broadcasting, but sometimes used as a hack to play NTSC content in PAL
  regions (e.g. on VCRs).
- PAL_N - PAL with alternative chroma subcarrier frequency,
  3.58205625 MHz. Used as a broadcast standard in Argentina, Paraguay
  and Uruguay to fit 576i50 with colour in 6 MHz channel raster.
- PAL60 - 480i60 signal with PAL-style color at normal European PAL
  frequency. Another non-standard, non-broadcast mode, used in similar
  contexts as NTSC_443. Some displays support one but not the other.
- SECAM - French frequency-modulated analog color standard; also have
  been broadcast in Eastern Europe and various parts of Africa and Asia.
  Uses the same 576i50 timings as PAL.

Also added some comments explaining color subcarrier frequency
registers.

Signed-off-by: Mateusz Kwiatkowski 
Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 58286acf4b9e..55f6f490877c 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -46,6 +46,7 @@
 #define VEC_CONFIG0_YDEL(x)((x) << 26)
 #define VEC_CONFIG0_CDEL_MASK  GENMASK(25, 24)
 #define VEC_CONFIG0_CDEL(x)((x) << 24)
+#define VEC_CONFIG0_SECAM_STD  BIT(21)
 #define VEC_CONFIG0_PBPR_FIL   BIT(18)
 #define VEC_CONFIG0_CHROMA_GAIN_MASK   GENMASK(17, 16)
 #define VEC_CONFIG0_CHROMA_GAIN_UNITY  (0 << 16)
@@ -76,6 +77,27 @@
 #define VEC_SOFT_RESET 0x10c
 #define VEC_CLMP0_START0x144
 #define VEC_CLMP0_END  0x148
+
+/*
+ * These set the color subcarrier frequency
+ * if VEC_CONFIG1_CUSTOM_FREQ is enabled.
+ *
+ * VEC_FREQ1_0 contains the most significant 16-bit half-word,
+ * VEC_FREQ3_2 contains the least significant 16-bit half-word.
+ * 0x8000 seems to be equivalent to the pixel clock
+ * (which itself is the VEC clock divided by 8).
+ *
+ * Reference values (with the default pixel clock of 13.5 MHz):
+ *
+ * NTSC  (3579545.[45] Hz) - 0x21F07C1F
+ * PAL   (4433618.75 Hz)   - 0x2A098ACB
+ * PAL-M (3575611.[888111] Hz) - 0x21E6EFE3
+ * PAL-N (3582056.25 Hz)   - 0x21F69446
+ *
+ * NOTE: For SECAM, it is used as the Dr center frequency,
+ * regardless of whether VEC_CONFIG1_CUSTOM_FREQ is enabled or not;
+ * that is specified as 4406250 Hz, which corresponds to 0x29C71C72.
+ */
 #define VEC_FREQ3_20x180
 #define VEC_FREQ1_00x184
 
@@ -118,6 +140,14 @@
 
 #define VEC_INTERRUPT_CONTROL  0x190
 #define VEC_INTERRUPT_STATUS   0x194
+
+/*
+ * Db center frequency for SECAM; the clock for this is the same as for
+ * VEC_FREQ3_2/VEC_FREQ1_0, which is used for Dr center frequency.
+ *
+ * This is specified as 425 Hz, which corresponds to 0x284BDA13.
+ * That is also the default value, so no need to set it explicitly.
+ */
 #define VEC_FCW_SECAM_B0x198
 #define VEC_SECAM_GAIN_VAL 0x19c
 
@@ -194,9 +224,13 @@ connector_to_vc4_vec(struct drm_connector *connector)
 
 enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_NTSC,
+   VC4_VEC_TV_MODE_NTSC_443,
VC4_VEC_TV_MODE_NTSC_J,
VC4_VEC_TV_MODE_PAL,
+   VC4_VEC_TV_MODE_PAL_60,
VC4_VEC_TV_MODE_PAL_M,
+   VC4_VEC_TV_MODE_PAL_N,
+   VC4_VEC_TV_MODE_SECAM,
 };
 
 struct vc4_vec_tv_mode {
@@ -234,6 +268,12 @@ static const struct debugfs_reg32 vec_regs[] = {
 };
 
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC_443,
+   .config0 = VEC_CONFIG0_NTSC_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x2a098acb,
+   },
{
.mode = DRM_MODE_TV_MODE_NTSC_M,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
@@ -244,6 +284,12 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   .mode = DRM_MODE_TV_MODE_PAL_60,
+   .config0 = VEC_CONFIG0_PAL_M_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x2a098acb,
+   },
{
.mode = DRM_MODE_TV_MODE_PAL_B,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
@@ -254,6 +300,17 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   .mode = DRM_MODE_TV_MODE_PAL_N,
+   .config0 = VEC_CONFIG0_PAL_N_STD,
+

[PATCH v2 38/41] drm/sun4i: tv: Remove useless destroy function

2022-08-29 Thread Maxime Ripard
Our destroy implementation is just calling the generic helper, so let's
just remove our function and directly use the helper.

Signed-off-by: Maxime Ripard 
Reviewed-by: Jernej Skrabec 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 52bbba8f19dc..6d7e1d51569a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -491,15 +491,9 @@ static const struct drm_connector_helper_funcs 
sun4i_tv_comp_connector_helper_fu
.get_modes  = sun4i_tv_comp_get_modes,
 };
 
-static void
-sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
-{
-   drm_connector_cleanup(connector);
-}
-
 static const struct drm_connector_funcs sun4i_tv_comp_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy= sun4i_tv_comp_connector_destroy,
+   .destroy= drm_connector_cleanup,
.reset  = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,

-- 
b4 0.10.0-dev-65ba7


[PATCH v2 35/41] drm/sun4i: tv: Convert to atomic hooks

2022-08-29 Thread Maxime Ripard
The sun4i TV driver still uses legacy enable and disable hook
implementation. Let's convert to the atomic variants.

Signed-off-by: Maxime Ripard 

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 53152d77c392..f7aad995ab5b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -339,7 +339,8 @@ static void sun4i_tv_mode_to_drm_mode(const struct tv_mode 
*tv_mode,
mode->vtotal = mode->vsync_end  + tv_mode->vback_porch;
 }
 
-static void sun4i_tv_disable(struct drm_encoder *encoder)
+static void sun4i_tv_disable(struct drm_encoder *encoder,
+   struct drm_atomic_state *state)
 {
struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
@@ -353,7 +354,8 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
sunxi_engine_disable_color_correction(crtc->engine);
 }
 
-static void sun4i_tv_enable(struct drm_encoder *encoder)
+static void sun4i_tv_enable(struct drm_encoder *encoder,
+   struct drm_atomic_state *state)
 {
struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
@@ -469,8 +471,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 }
 
 static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
-   .disable= sun4i_tv_disable,
-   .enable = sun4i_tv_enable,
+   .atomic_disable = sun4i_tv_disable,
+   .atomic_enable  = sun4i_tv_enable,
.mode_set   = sun4i_tv_mode_set,
 };
 

-- 
b4 0.10.0-dev-65ba7


[PULL] drm-intel-next

2022-08-29 Thread Jani Nikula


Hi Dave & Daniel -

drm-intel-next-2022-08-29:
drm/i915 feature pull for v6.1:

Features and functionality:
- Early Meteorlake (MTL) enabling (José, Radhakrishna, Clint, Imre, Vandita, 
Ville, Jani)
- Support more HDMI pixel clock frequencies on DG2 (Clint)
- Sanity check PCI BARs (Piotr Piórkowski)
- Enable DC5 on DG2 (Anusha)
- DG2 DMC firmware version bump to v2.07 (Madhumitha)
- New ADL-S PCI ID (José)

Refactoring and cleanups:
- Add display sub-struct to struct drm_i915_private (Jani)
- Add initial runtime info to device info (Jani)
- Split out HDCP and backlight registers to separate files (Jani)

Fixes:
- Skip wm/ddb readout for disabled pipes (Ville)
- HDMI port timing quirk for GLK ECS Liva Q2 (Diego Santa Cruz)
- Fix bw init null pointer dereference (Łukasz Bartosik)
- Disable PPS power hook for DP AUX backlight (Jouni)
- Avoid warnings on registering multiple backlight devices (Arun)
- Fix dual-link DSI backlight and CABC ports for display 11+ (Jani)
- Fix Type-C PHY ownership programming in HDMI legacy mode (Imre)
- Fix unclaimed register access while loading PIPEDMC-C/D (Imre)
- Bump up CDCLK for DG2 (Stan)
- Prune modes that require HDMI 2.1 FRL (Ankit)
- Disable FBC when PSR1 is enabled in display 12-13 (Matt)
- Fix TGL+ HDMI transcoder clock and DDI BUF disable order (Imre)
- Disable PSR before disable pipe (José)
- Disable DMC handlers during firmware loading/disabling on display 12+ (Imre)
- Disable clock gating for PIPEDMC-A/B as a workaround (Imre)

Merges:
- Two drm-next backmerges (Rodrigo, Jani)

BR,
Jani.

The following changes since commit 2c2d7a67defa198a8b8148dbaddc9e5554efebc8:

  Merge tag 'drm-intel-gt-next-2022-08-24' of 
git://anongit.freedesktop.org/drm/drm-intel into drm-next (2022-08-26 10:03:43 
+1000)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm-intel tags/drm-intel-next-2022-08-29

for you to fetch changes up to 917bda9ab155032a02be1a57ebd4d949ae9e1528:

  Merge drm/drm-next into drm-intel-next (2022-08-29 15:14:59 +0300)


drm/i915 feature pull for v6.1:

Features and functionality:
- Early Meteorlake (MTL) enabling (José, Radhakrishna, Clint, Imre, Vandita, 
Ville, Jani)
- Support more HDMI pixel clock frequencies on DG2 (Clint)
- Sanity check PCI BARs (Piotr Piórkowski)
- Enable DC5 on DG2 (Anusha)
- DG2 DMC firmware version bump to v2.07 (Madhumitha)
- New ADL-S PCI ID (José)

Refactoring and cleanups:
- Add display sub-struct to struct drm_i915_private (Jani)
- Add initial runtime info to device info (Jani)
- Split out HDCP and backlight registers to separate files (Jani)

Fixes:
- Skip wm/ddb readout for disabled pipes (Ville)
- HDMI port timing quirk for GLK ECS Liva Q2 (Diego Santa Cruz)
- Fix bw init null pointer dereference (Łukasz Bartosik)
- Disable PPS power hook for DP AUX backlight (Jouni)
- Avoid warnings on registering multiple backlight devices (Arun)
- Fix dual-link DSI backlight and CABC ports for display 11+ (Jani)
- Fix Type-C PHY ownership programming in HDMI legacy mode (Imre)
- Fix unclaimed register access while loading PIPEDMC-C/D (Imre)
- Bump up CDCLK for DG2 (Stan)
- Prune modes that require HDMI 2.1 FRL (Ankit)
- Disable FBC when PSR1 is enabled in display 12-13 (Matt)
- Fix TGL+ HDMI transcoder clock and DDI BUF disable order (Imre)
- Disable PSR before disable pipe (José)
- Disable DMC handlers during firmware loading/disabling on display 12+ (Imre)
- Disable clock gating for PIPEDMC-A/B as a workaround (Imre)

Merges:
- Two drm-next backmerges (Rodrigo, Jani)


Ankit Nautiyal (1):
  drm/i915/hdmi: Prune modes that require HDMI2.1 FRL

Anusha Srivatsa (3):
  drm/i915/display: Cleanup intel_phy_is_combo()
  drm/i915: Pass drm_i915_private struct instead of gt for 
gen11_gu_misc_irq_handler/ack()
  drm/i915/dg2: Add support for DC5 state

Arun R Murthy (1):
  drm/i915/display: avoid warnings when registering dual panel backlight

Bo Liu (1):
  drm/i915/irq: Fix a "the the" typo

Clint Taylor (1):
  drm/i915/mtl: Fix rawclk for Meteorlake PCH

Diego Santa Cruz (1):
  drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk

Imre Deak (6):
  drm/i915/tgl+: Fix HDMI transcoder clock vs. DDI BUF disabling order
  drm/i915/d12+: Disable DMC handlers during loading/disabling the firmware
  drm/i915/d13: Add Wa_16015201720 disabling clock gating for PIPEDMC-A/B
  drm/i915/xelpd: Fix unclaimed accesses while loading PIPEDMC-C/D
  drm/i915/tc: Fix PHY ownership programming in HDMI legacy mode
  drm/i915/mtl: Add VBT port and AUX_CH mapping

Jani Nikula (42):
  drm/i915/hdcp: split out hdcp registers to a separate file
  drm/i915/hdcp: replace BIT() with REG_BIT() in register definitions
  drm/i915/backlight: split out backlight registers to a separate file
  drm/i915/dsi: filter invalid backlight and CABC port

Re: [PATCH 1/2] drm/etnaviv: add HWDB entry for GC7000 r6203

2022-08-29 Thread Lucas Stach
Hi Stefan,

please keep the CC list intact when replying. I've almost missed this.

Am Montag, dem 29.08.2022 um 13:41 +0200 schrieb Stefan Eschenbacher:
> 
> Product_id, customer_id and eco_id should not be zero. The different
> versions of model 0x7000, revision 0x6203 can differ in stream_count,
> minor_feature5 and minor_features7.
>  
>     {
>    .model = 0x7000,
>    .revision = 0x6203,
>    .product_id = 0x70003,
>    .customer_id = 0x4,
>    .eco_id = 0,
>    .stream_count = 16,
>    .register_max = 64,
>    .thread_count = 512,
>    .shader_core_count = 2,
>    .vertex_cache_size = 16,
>    .vertex_output_buffer_size = 1024,
>    .pixel_pipes = 1,
>    .instruction_count = 512,
>    .num_constants = 320,
>    .buffer_size = 0,
>    .varyings_count = 16,
>    .features = 0xe0287c8d,
>    .minor_features0 = 0xc1799eff,
>    .minor_features1 = 0xfefbfad9,
>    .minor_features2 = 0xeb9d4fbf,
>    .minor_features3 = 0xedfffced,
>    .minor_features4 = 0xdb0dafc7,
>    .minor_features5 = 0x3b5ac333,
>    .minor_features6 = 0xfcce6000,
>    .minor_features7 = 0xfffbfa6f,
>    .minor_features8 = 0x00e10ef3,
>    .minor_features9 = 0x00c8003c,
>    .minor_features10 = 0x4040,
>    .minor_features11 = 0x0024,
>     },
>     {
>    .model = 0x7000,
>    .revision = 0x6203,
>    .product_id = 0x7000f,
>    .customer_id = 0x60,
>    .eco_id = 0,
>    .stream_count = 8,
>    .register_max = 64,
>    .thread_count = 512,
>    .shader_core_count = 2,
>    .vertex_cache_size = 16,
>    .vertex_output_buffer_size = 1024,
>    .pixel_pipes = 1,
>    .instruction_count = 512,
>    .num_constants = 320,
>    .buffer_size = 0,
>    .varyings_count = 16,
>    .features = 0xe0287c8d,
>         .minor_features0 = 0xc1799eff,
>    .minor_features1 = 0xfefbfad9,
>    .minor_features2 = 0xeb9d4fbf,
>    .minor_features3 = 0xedfffced,
>    .minor_features4 = 0xdb0dafc7,
>    .minor_features5 = 0x7b5ac333,
>    .minor_features6 = 0xfcce6000,
>    .minor_features7 = 0x1bfbfa6f,
>    .minor_features8 = 0x00e10ef0,
>    .minor_features9 = 0x00c8003c,
>    .minor_features10 = 0x4040,
>    .minor_features11 = 0x0024,
>     },
> 
> Take a look in the stm32 hwdb file.

While your comment is correct and we should do a more targeted
matching, could you please point me to the stm32 hwdb file you are
referring to?

Regards,
Lucas



Re: [PATCH 3/3] drm: omapdrm: Do no allocate non-scanout GEMs through DMM/TILER

2022-08-29 Thread Ivaylo Dimitrov

Hi,


On 29.08.22 г. 5:51 ч., Yongqin Liu wrote:

Hi, Ivaylo

Sorry for the late response, and Thanks very much for the detailed explanations!

On Thu, 18 Aug 2022 at 18:23, Ivaylo Dimitrov
 wrote:


Hi,

On 17.08.22 г. 7:52 ч., Yongqin Liu wrote:

Hi, Ivaylo

On Mon, 15 Aug 2022 at 14:23, Ivaylo Dimitrov
 wrote:


Hi Liu,

On 14.08.22 г. 17:27 ч., Yongqin Liu wrote:

Hi, IvayIo

Thanks very much for the reply!

On Sat, 13 Aug 2022 at 14:58, Ivaylo Dimitrov
 wrote:


Hi Liu,

On 12.08.22 г. 7:35 ч., Yongqin Liu wrote:

Hi, Ivaylo, Tomi

We have one X15 Android AOSP master build, it could not have the home
screen displayed
on the hdmi monitor connected with this change, with the following
message printed on the serial console
[  607.404205] omapdrm omapdrm.0: Failed to setup plane plane-0
[  607.410522] omapdrm omapdrm.0: Failed to setup plane plane-1
[  607.416381] omapdrm omapdrm.0: Failed to setup plane plane-2
[  607.422088] omapdrm omapdrm.0: Failed to setup plane plane-3

   # for details, please check the link here: http://ix.io/47m1

It will work with home screen displayed on the hdmi monitor if this
change is reverted.

Is this the broken problem you talked about here?

And could you please give some suggestions on how to have the x15
Android build work with this change?



Make sure scanout (i.e. those to be displayed) buffers are actually
allocated as such - OMAP_BO_SCANOUT flag must be set when calling
omap_bo_new().


I am not familiar with this area, I am sorry if I asked quite silly questions:(
I googled omap_bo_new, and found it's a function of libdrm here[1], is
it what you meant here?



Yes, calling this function from userspace ends in kernel code the
$subject patch is part of.


If it's the omap_bo_new that we should pass OMAP_BO_SCANOUT when it is called,
then is it the correct way to update omap_bo_new to add the OMAP_BO_SCANOUT flag
before it calls omap_bo_new_impl?



omap_bo_new() is fine and does not need any updates/fixes, it is the
code that uses it (whoever it is, I am not familiar with the userspace
you are using) that shall pass correct flags (third parameter) when
calling it.


Sorry, I do not get the point here.
Like you said, the code that calls omap_bo_new needs to pass OMAP_BO_SCANOUT,
then IMO omap_bo_new should be the best place to add the OMAP_BO_SCANOUT flag,
(like via flags = flags | OMAP_BO_SCANOUT), that could help avoid
missing the flag by some code,
and also avoids hacks/changes on the possible blob binaries.

Do I misunderstand somewhere?
Or is there some case that OMAP_BO_SCANOUT shouldn't be passed when
omap_bo_new is called?



Exactly. You need to pass OMAP_BO_SCANOUT only when you want your
buffers to be 'scanout' buffers(i.e. buffers that can be displayed on
screen), which is not always the case - there is no need offscreen
buffers or pixmaps to be scanout capable, for example. There are more
cases like that.

The problem is that scanout buffer on OMAP4 allocate additional
resources in DMM/TILER (a piece of hardware) and those resources are
limited. Not only that, but DMM/TILER memory space eventually gets
fragmented over time (if you have lots of allocataoins/deallocations)
and you will start getting ENOMEM (or similar) errors.

Ofc, in your particular use case you may never hit such issues.


Thanks, I understand the cases now.



BTW you shall really find who and how uses OMAP BO API, in theory it
might use ioctls directly and not call omap_bo_xxx functions.


Do you mean the DRM_OMAP_GEM_NEW ioctl api?
There is no place in the AOSP tree to call that except the
omap_bo_new_impl function,
which is called by the omap_bo_new and omap_bo_new_tiled functions.
The omap_bo_new should not be called with the OMAP_BO_TILED flag,
while the omap_bo_new_tiled should be called with the OMAP_BO_TILED flag

Regarding to the omap_bo_new function, there are 2 places call it in
the AOSP tree:
#1 ./external/libkmsxx/kms++/src/omap/omapframebuffer.cpp
#2 ./device/ti/beagle_x15/gpu/gralloc.am57x.so

#1 seems not used in AOSP yet, and #2 is one blob binary we do not
have the source for.



I would bet on gralloc.am57x.so.

yeah, that's my guess as well.


strace
would be your friend there. or gdb, or whatever tools are used on
android. Or put some printfs() in omap_bo_new() that output the PID of
the calling process, etc.


Thanks a lot for these great suggestions! Will use them when possible.


And another question is that, since the userspace(libdrm) will be used
to work with different kernel versions,
like the old 4.14, 4.19, etc, do you think there will be problem to
pass  OMAP_BO_SCANOUT
from the userspace side with the old kernels(which does not have this change)?
does this change need to be backported to the old kernel versions?


There should not be any issue. The changes could be backported if one
hits the issues this $series is fixing, but there is no need.


Thanks for the confirmation!
I just boot-tested with adding OMAP_BO_SCA

Re: [PATCH v1 04/35] drm/modes: Introduce 480i and 576i modes

2022-08-29 Thread Maxime Ripard
Hi Mateusz

On Wed, Aug 24, 2022 at 06:42:18PM +0200, Mateusz Kwiatkowski wrote:
> Hi Maxime,
> 
> W dniu 18.08.2022 o 17:56, Geert Uytterhoeven pisze:
> > Hi Maxime,
> >
> > On Thu, Aug 18, 2022 at 5:46 PM Maxime Ripard  wrote:
> >> On Thu, Aug 18, 2022 at 05:34:30PM +0200, Geert Uytterhoeven wrote:
> >>> On Thu, Aug 18, 2022 at 3:42 PM Maxime Ripard  wrote:
>  I started adding more sanity checks to my code, and I just realised I
>  don't seem to be able to reach 720 pixels over a single line though. If
>  I understood it properly, and according to [1] the active part of a line
>  is supposed to be 51.95us, and the blanking period taking 12.05us. [2]
>  in the timing section has pretty much the same numbers, so it looks
>  sane.
> 
>  At 13.5Mhz, a pixel is going to take roughly 74ns, and 51950 / 74 = 702
>  pixels
> 
>  It seems we can go push it to 52350 ns, but that still gives us only 706
>  pixels.
> 
>  Similarly, if I just choose to ignore that limit and just take the
>  active time I need, 720 * 74 = 53280ns
> 
>  That leaves us 10720ns for the blanking period, and that's not enough to
>  fit even the minimum of the front porch, hsync and back porch (1.55 +
>  4.5 + 5.5 = 11.55us).
> 
>  Are those constraints merely recommendations, or am I missing something?
> >>>
> >>> You are missing that the parts near the borders of the full image are
> >>> part of the overscan range, and may or may not be visible, depending
> >>> on your actual display.
> >>> The full 768x576 image size from BT.656 is not visible on a typical PAL 
> >>> display,
> >>> and is more of an "absolute maximum rating", guaranteed to cover more
> >>> than analog PAL.
> >>
> >> So the overscan range is not part of the active area, unlike what HDMI
> >> is doing for example?
> >
> > Indeed. DVI-D and HDMI etc. are pure digital (let's ignore they are a
> > digitized variant of old analog VGA ;-), hence there is a one-to-one
> > match between pixels in the image and pixels on the screen (ignoring
> > scaling).  But even when using an analog VGA input on a modern
> > digital display, you have controls to e.g. move the image.
> >
> >> Is there some minimal timings available somewhere to fit those absolute
> >> maximum ratings?
> >
> > I guess they can be found on the Internet...
> 
> Here are some references that I personally found useful:
> 
> - ITU-R BT.601 
>   This is *the* standard that pretty much every modern device that deals with
>   analog-style TV signal follows then converting to and from the digital 
> domain.
>   For example in the figures on page 10 (12 in the PDF numbering) you can see
>   that the "time datum", i.e. start of horizontal sync pulse is canonically
>   supposed to happen on sample 732 for 50 Hz or sample 736 for 59.94 Hz modes.
> 
>   BT.601 assumes 13.5 MHz sample rate / pixel clock, but you can 
> proportionally
>   scale those for other pixel clocks.
> 
> - ITU-R BT.1700 
>   This is *the* standard in force for actual analog composite video signals.
>   The vertical sync specs are discrete, so they don't really change between
>   analog and digital domains. For horizontal sync, the values in those specs
>   are given in microseconds/nanoseconds, but you can multiply those by the
>   sampling rate for equivalent pixel counts.
> 
> - Pembers' Ponderings
>   
> 
>   An old archived website with a ton of resources about analog TV.
>   The "Line Standards" article will probably be most interesting to you.

Thanks so much for all those resources, it's been super helpful :)

> By the way, please note a couple of things:
> 
> - The analog standards are very imprecise for modern digital norms, giving
>   considerable leeway for just about every timing. The allowed leeways are
>   usually equivalent to a couple of pixels at the standard 13.5 MHz sampling
>   rate - and those are meant for the transmitting end. Receivers are usually
>   much more forgiving to maximize compatibility.

Ok

> - The 720-pixel standard of BT.601 is considerably wider than the active width
>   specified in the analog standards. AFAIK this is intentional, to ensure that
>   no part of the actual image is missed during digitization, and to keep the
>   number a nice multiply of 16. The picture width given in the analog 
> standards
>   is equivalent to somewhere between 702 and 714 pixels (at 13.5 MHz clock),
>   depending on the specific standard. And that includes overscan.

Ok. I think it still makes sense to allow it, if only we were using it so far :)

I've done a first implementation in the v2 I just sent that seems to
work ok, please let me know if I did anything stupid :)

In particular, I chose, if we were between 702 and 720 pixels to disable
all duration checks, and take the missing time 

Re: [PATCH] drm/bridge: sii902x: add support for DRM_BRIDGE_ATTACH_NO_CONNECTOR

2022-08-29 Thread Neil Armstrong

On 25/08/2022 14:48, Linus Walleij wrote:

On Wed, Aug 17, 2022 at 3:31 PM Neil Armstrong  wrote:

On 15/08/2022 02:15, Dmitry Osipenko wrote:

08.08.2022 12:51, Neil Armstrong пишет:

On 08/08/2022 11:15, Neil Armstrong wrote:



This patch broke ARM/QEMU vexpress display because of_drm_find_bridge()
always fail with -EPROBE_DEFER. Reverting this patch returns display
back. Please fix or revert, thanks in advance.


Can you share a QEMU cmdline to reproduce ?


Actually the vexpress DT has multiple input ports instead of a single
input port at @0
and an output port at @1 like documented in the bindings:

vexpress-v2m.dtsi#L303-L307:
ports {
  #address-cells = <1>;
  #size-cells = <0>;

  /*
   * Both the core tile and the motherboard routes their output
   * pads to this transmitter. The motherboard system controller
   * can select one of them as input using a mux register in
   * "arm,vexpress-muxfpga". The Vexpress with the CA9 core tile is
   * the only platform with this specific set-up.
   */
  port@0 {
  reg = <0>;
  dvi_bridge_in_ct: endpoint {
  remote-endpoint = <&clcd_pads_ct>;
  };
  };
  port@1 {
  reg = <1>;
  dvi_bridge_in_mb: endpoint {
  remote-endpoint = <&clcd_pads_mb>;
  };
  };
};

bindings:
ports:
  $ref: /schemas/graph.yaml#/properties/ports

  properties:
port@0:
  $ref: /schemas/graph.yaml#/properties/port
  description: Parallel RGB input port

port@1:
  $ref: /schemas/graph.yaml#/properties/port
  description: HDMI output port

port@3:
  $ref: /schemas/graph.yaml#/properties/port
  description: Sound input port

The patch is conform to the bindings, the DT was working but is actually
not valid.


I haven't looked closely at how to fix this properly, but if we can fix
it using of_machine_is_compatible("arm,vexpress") workaround in the
driver, then it will be good enough at least as a temporal fix, IMO.


If other maintainers are ok with that, it can be temporary fix until the DT 
gets fixed.


That's fine with me, will you send a patch?


Who, me ?



I don't know how you expect the DT to get "fixed" though.

The hardware looks like this, it's maybe not the most elegant
electronics design but it exists, so... I wrote this DT with two
inputs, see commit f1fe12c8bf332, the code handling this
awkward mux is part of the DRM driver, see
drivers/gpu/drm/pl111/pl111_versatile.c function
pl111_vexpress_clcd_init() for an idea of how it works.


The proper fix would be the other way around, adding a mux bridge before the 
sii902x
returning the next bridge or nothing to the right controller.



Yours,
Linus Walleij


Neil


[PATCH v4 0/8] drm/vc4: Reset HDMI link at hotplug

2022-08-29 Thread Maxime Ripard
Hi,

This is a follow-up of the work to support the interactions between the hotplug
and the scrambling support for vc4:

https://lore.kernel.org/dri-devel/20210507150515.257424-11-max...@cerno.tech/
https://lore.kernel.org/dri-devel/20211025152903.1088803-10-max...@cerno.tech/
https://lore.kernel.org/dri-devel/2028103814.524670-1-max...@cerno.tech/

Ville feedback was that the same discussion happened some time ago for i915,
and resulted in a function to do an full disable/enable cycle on reconnection
to avoid breaking the HDMI 2.0 spec.

While the previous versions of this series was moving the current scrambling
related functions into generic helpers to consolidate that logic, it proved to
be difficult to rework existing drivers to make use of it without hardware to
test it on and thus the code is (for now) private to vc4.

I still believe that long term, the code to decide if the scrambler needs to be
enabled or not should be moved into a generic helper.

This also means that we would need to move the format output decision to a
generic helper, which also makes sense to me but it probably going to be
controversial.

Let me know what you think,
Maxime

Changes from v3 
(https://lore.kernel.org/dri-devel/20220714091252.2089015-1-max...@cerno.tech/):
  - Rebased on drm-misc-next-2022-08-20-1

Changes from v2 
(https://lore.kernel.org/dri-devel/2028103814.524670-1-max...@cerno.tech/):
  - Rebased on next-20220713
  - Dropped the generic helpers and put them into vc4

Changes from v1 
(https://lore.kernel.org/dri-devel/20211102145944.259181-1-max...@cerno.tech/):
  - Dropped the 340MHz define
  - Make drm_mode_hdmi_requires_scrambling use the bpc
  - Make more drm_display_mode const in vc4
  - Dropped the tegra conversion
  - Added more comments

Maxime Ripard (8):
  drm/vc4: hdmi: Constify drm_display_mode
  drm/vc4: hdmi: Remove unused argument in vc4_hdmi_supports_scrambling
  drm/vc4: hdmi: Remove mutex in detect
  drm/vc4: hdmi: Simplify the hotplug handling
  drm/vc4: hdmi: Switch to detect_ctx
  drm/vc4: hdmi: Move vc4_hdmi_supports_scrambling() around
  drm/vc4: hdmi: Reset link on hotplug
  drm/scdc: Document hotplug gotchas

 drivers/gpu/drm/display/drm_scdc_helper.c |  13 +
 drivers/gpu/drm/vc4/vc4_hdmi.c| 308 ++
 drivers/gpu/drm/vc4/vc4_hdmi.h|  12 +-
 3 files changed, 218 insertions(+), 115 deletions(-)

-- 
2.37.1



[PATCH v4 1/8] drm/vc4: hdmi: Constify drm_display_mode

2022-08-29 Thread Maxime Ripard
We don't modify the drm_display_mode pointer we have in the driver in
most places, so let's make them const.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 16 
 drivers/gpu/drm/vc4/vc4_hdmi.h |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 84e5a91c2ea7..4a8c902dbbc8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -335,7 +335,7 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
 
if (vc4_hdmi->disable_4kp60) {
struct drm_device *drm = connector->dev;
-   struct drm_display_mode *mode;
+   const struct drm_display_mode *mode;
 
list_for_each_entry(mode, &connector->probed_modes, head) {
if (vc4_hdmi_mode_needs_scrambling(mode, 8, 
VC4_HDMI_OUTPUT_RGB)) {
@@ -709,7 +709,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder 
*encoder)
 }
 
 static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder,
-struct drm_display_mode *mode)
+const struct drm_display_mode *mode)
 {
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
@@ -732,7 +732,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder 
*encoder)
 {
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_device *drm = vc4_hdmi->connector.dev;
-   struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
+   const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
unsigned long flags;
int idx;
 
@@ -1077,7 +1077,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
 
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 struct drm_connector_state *state,
-struct drm_display_mode *mode)
+const struct drm_display_mode *mode)
 {
struct drm_device *drm = vc4_hdmi->connector.dev;
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -1141,7 +1141,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi 
*vc4_hdmi,
 
 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 struct drm_connector_state *state,
-struct drm_display_mode *mode)
+const struct drm_display_mode *mode)
 {
struct drm_device *drm = vc4_hdmi->connector.dev;
const struct vc4_hdmi_connector_state *vc4_state =
@@ -1303,7 +1303,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct 
drm_encoder *encoder,
drm_atomic_get_new_connector_state(state, connector);
struct vc4_hdmi_connector_state *vc4_conn_state =
conn_state_to_vc4_hdmi_conn_state(conn_state);
-   struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
+   const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate;
unsigned long bvb_rate, hsm_rate;
unsigned long flags;
@@ -1416,7 +1416,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct 
drm_encoder *encoder,
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_device *drm = vc4_hdmi->connector.dev;
struct drm_connector *connector = &vc4_hdmi->connector;
-   struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
+   const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
struct drm_connector_state *conn_state =
drm_atomic_get_new_connector_state(state, connector);
unsigned long flags;
@@ -1444,7 +1444,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct 
drm_encoder *encoder,
 {
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_device *drm = vc4_hdmi->connector.dev;
-   struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
+   const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 99b0bc1297be..79495ef79f09 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -72,7 +72,7 @@ struct vc4_hdmi_variant {
/* Callback to configure the video timings in the HDMI block */
void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
-   struct drm_display_mode *mode);
+ 

[PATCH v4 2/8] drm/vc4: hdmi: Remove unused argument in vc4_hdmi_supports_scrambling

2022-08-29 Thread Maxime Ripard
Even though vc4_hdmi_supports_scrambling takes a mode as an argument, it
never uses it. Let's remove it.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4a8c902dbbc8..faf52c20b95b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -708,8 +708,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder 
*encoder)
vc4_hdmi_set_hdr_infoframe(encoder);
 }
 
-static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder,
-const struct drm_display_mode *mode)
+static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder)
 {
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
@@ -738,7 +737,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder 
*encoder)
 
lockdep_assert_held(&vc4_hdmi->mutex);
 
-   if (!vc4_hdmi_supports_scrambling(encoder, mode))
+   if (!vc4_hdmi_supports_scrambling(encoder))
return;
 
if (!vc4_hdmi_mode_needs_scrambling(mode,
-- 
2.37.1



Re: [PATCH] drm/amd/amdgpu: Add modeset module parameter support

2022-08-29 Thread Alex Deucher
On Mon, Aug 29, 2022 at 9:43 AM Zhen Ni  wrote:
>
> Nomodeset kernel parameter is for all graphics cards. Amdgpu cannot
> be set separately in some scenarios, such as hybrid graphics(i + a).
> Add modeset module parameter for amdgpu to set kernel mode separately.
>
> Signed-off-by: Zhen Ni 

amdgpu didn't support this option since it never supported the legacy
drm mode that other older drivers did.  If you just want the option to
keep the driver from loading, you can already do this by blacklisting
the driver.  E.g.,
modprobe.blacklist=amdgpu

Alex

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 13 -
>  1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 429fcdf28836..856a70370e3c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -107,6 +107,7 @@
>  #define KMS_DRIVER_MINOR   48
>  #define KMS_DRIVER_PATCHLEVEL  0
>
> +int amdgpu_modeset = -1;
>  int amdgpu_vram_limit;
>  int amdgpu_vis_vram_limit;
>  int amdgpu_gart_size = -1; /* auto */
> @@ -199,6 +200,13 @@ struct amdgpu_watchdog_timer amdgpu_watchdog_timer = {
> .period = 0x0, /* default to 0x0 (timeout disable) */
>  };
>
> +/**
> + * DOC: modeset (int)
> + * Disable/Enable kernel modesetting (1 = enable, 0 = disable, -1 = auto 
> (default)).
> + */
> +MODULE_PARM_DESC(modeset, "Disable/Enable kernel modesetting");
> +module_param_named(modeset, amdgpu_modeset, int, 0400);
> +
>  /**
>   * DOC: vramlimit (int)
>   * Restrict the total amount of VRAM in MiB for testing.  The default is 0 
> (Use full VRAM).
> @@ -2753,7 +2761,10 @@ static int __init amdgpu_init(void)
>  {
> int r;
>
> -   if (drm_firmware_drivers_only())
> +   if (drm_firmware_drivers_only() && amdgpu_modeset == -1)
> +   amdgpu_modeset = 0;
> +
> +   if (amdgpu_modeset == 0)
> return -EINVAL;
>
> r = amdgpu_sync_init();
> --
> 2.20.1
>


[PATCH v4 4/8] drm/vc4: hdmi: Simplify the hotplug handling

2022-08-29 Thread Maxime Ripard
Our detect callback has a bunch of operations to perform depending on
the current and last status of the connector, such a setting the CEC
physical address or enabling the scrambling again.

This is currently dealt with a bunch of if / else statetements that make
it fairly difficult to read and extend.

Let's move all that logic to a function of its own.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 66 ++
 1 file changed, 44 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index b786645eaeb7..9fad57ebdd11 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -273,17 +273,53 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi 
*vc4_hdmi) {}
 
 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder);
 
+static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
+   enum drm_connector_status status)
+{
+   struct drm_connector *connector = &vc4_hdmi->connector;
+   struct edid *edid;
+
+   /*
+* NOTE: This function should really be called with
+* vc4_hdmi->mutex held, but doing so results in reentrancy
+* issues since cec_s_phys_addr_from_edid might call
+* .adap_enable, which leads to that funtion being called with
+* our mutex held.
+*
+* Concurrency isn't an issue at the moment since we don't share
+* any state with any of the other frameworks so we can ignore
+* the lock for now.
+*/
+
+   if (status == connector->status)
+   return;
+
+   if (status == connector_status_disconnected) {
+   cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
+   return;
+   }
+
+   edid = drm_get_edid(connector, vc4_hdmi->ddc);
+   if (!edid)
+   return;
+
+   cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
+   kfree(edid);
+
+   vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
-   bool connected = false;
+   enum drm_connector_status status = connector_status_disconnected;
 
/*
 * NOTE: This function should really take vc4_hdmi->mutex, but
 * doing so results in reentrancy issues since
-* cec_s_phys_addr_from_edid might call .adap_enable, which
-* leads to that funtion being called with our mutex held.
+* vc4_hdmi_handle_hotplug() can call into other functions that
+* would take the mutex while it's held here.
 *
 * Concurrency isn't an issue at the moment since we don't share
 * any state with any of the other frameworks so we can ignore
@@ -294,31 +330,17 @@ vc4_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
 
if (vc4_hdmi->hpd_gpio) {
if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))
-   connected = true;
+   status = connector_status_connected;
} else {
if (vc4_hdmi->variant->hp_detect &&
vc4_hdmi->variant->hp_detect(vc4_hdmi))
-   connected = true;
+   status = connector_status_connected;
}
 
-   if (connected) {
-   if (connector->status != connector_status_connected) {
-   struct edid *edid = drm_get_edid(connector, 
vc4_hdmi->ddc);
-
-   if (edid) {
-   cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, 
edid);
-   kfree(edid);
-   }
-   }
-
-   vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base);
-   pm_runtime_put(&vc4_hdmi->pdev->dev);
-   return connector_status_connected;
-   }
-
-   cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
+   vc4_hdmi_handle_hotplug(vc4_hdmi, status);
pm_runtime_put(&vc4_hdmi->pdev->dev);
-   return connector_status_disconnected;
+
+   return status;
 }
 
 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
-- 
2.37.1



[PATCH v4 3/8] drm/vc4: hdmi: Remove mutex in detect

2022-08-29 Thread Maxime Ripard
We recently introduced a new mutex to protect concurrent execution of
ALSA and KMS hooks, and the concurrent access to some of vc4_hdmi
fields.

However, using it in the detect hook was creating a reentrency issue
with CEC code. Indeed, calling cec_s_phys_addr_from_edid from detect
might call the CEC adap_enable hook with the lock held, eventually
resulting in a deadlock.

Since we didn't really need to protect anything at the moment in the CEC
code, the decision was made to ignore the mutex in those CEC hooks,
working around the issue.

However, we can have the same thing happening if we end up triggering a
mode set from the detect callback, for example using
drm_atomic_helper_connector_hdmi_reset_link().

Since we don't really need to protect anything in detect either, let's
just drop the lock in detect, and add it again in CEC.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 88 +-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 +---
 2 files changed, 34 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index faf52c20b95b..b786645eaeb7 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -279,7 +279,16 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
bool connected = false;
 
-   mutex_lock(&vc4_hdmi->mutex);
+   /*
+* NOTE: This function should really take vc4_hdmi->mutex, but
+* doing so results in reentrancy issues since
+* cec_s_phys_addr_from_edid might call .adap_enable, which
+* leads to that funtion being called with our mutex held.
+*
+* Concurrency isn't an issue at the moment since we don't share
+* any state with any of the other frameworks so we can ignore
+* the lock for now.
+*/
 
WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
 
@@ -304,13 +313,11 @@ vc4_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
 
vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base);
pm_runtime_put(&vc4_hdmi->pdev->dev);
-   mutex_unlock(&vc4_hdmi->mutex);
return connector_status_connected;
}
 
cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
pm_runtime_put(&vc4_hdmi->pdev->dev);
-   mutex_unlock(&vc4_hdmi->mutex);
return connector_status_disconnected;
 }
 
@@ -320,14 +327,21 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
int ret = 0;
struct edid *edid;
 
-   mutex_lock(&vc4_hdmi->mutex);
+   /*
+* NOTE: This function should really take vc4_hdmi->mutex, but
+* doing so results in reentrancy issues since
+* cec_s_phys_addr_from_edid might call .adap_enable, which
+* leads to that funtion being called with our mutex held.
+*
+* Concurrency isn't an issue at the moment since we don't share
+* any state with any of the other frameworks so we can ignore
+* the lock for now.
+*/
 
edid = drm_get_edid(connector, vc4_hdmi->ddc);
cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
-   if (!edid) {
-   ret = -ENODEV;
-   goto out;
-   }
+   if (!edid)
+   return -ENODEV;
 
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
@@ -345,9 +359,6 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
}
}
 
-out:
-   mutex_unlock(&vc4_hdmi->mutex);
-
return ret;
 }
 
@@ -2663,17 +2674,6 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
int ret;
int idx;
 
-   /*
-* NOTE: This function should really take vc4_hdmi->mutex, but doing so
-* results in a reentrancy since cec_s_phys_addr_from_edid() called in
-* .detect or .get_modes might call .adap_enable, which leads to this
-* function being called with that mutex held.
-*
-* Concurrency is not an issue for the moment since we don't share any
-* state with KMS, so we can ignore the lock for now, but we need to
-* keep it in mind if we were to change that assumption.
-*/
-
if (!drm_dev_enter(drm, &idx))
/*
 * We can't return an error code, because the CEC
@@ -2688,6 +2688,8 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
return ret;
}
 
+   mutex_lock(&vc4_hdmi->mutex);
+
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
val = HDMI_READ(HDMI_CEC_CNTRL_5);
@@ -2722,6 +2724,7 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
 
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+   mutex_unlock(&vc4_hdmi->mutex);
drm_dev_exit

[PATCH v4 5/8] drm/vc4: hdmi: Switch to detect_ctx

2022-08-29 Thread Maxime Ripard
We'll need the locking context in future patch, so let's convert .detect
to .detect_ctx.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9fad57ebdd11..d385003d7f42 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -309,8 +309,9 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi 
*vc4_hdmi,
vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base);
 }
 
-static enum drm_connector_status
-vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
+struct drm_modeset_acquire_ctx *ctx,
+bool force)
 {
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
enum drm_connector_status status = connector_status_disconnected;
@@ -452,7 +453,6 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector 
*connector)
 }
 
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
-   .detect = vc4_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.reset = vc4_hdmi_connector_reset,
.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
@@ -460,6 +460,7 @@ static const struct drm_connector_funcs 
vc4_hdmi_connector_funcs = {
 };
 
 static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs 
= {
+   .detect_ctx = vc4_hdmi_connector_detect_ctx,
.get_modes = vc4_hdmi_connector_get_modes,
.atomic_check = vc4_hdmi_connector_atomic_check,
 };
-- 
2.37.1



[PATCH v4 6/8] drm/vc4: hdmi: Move vc4_hdmi_supports_scrambling() around

2022-08-29 Thread Maxime Ripard
We'll need it earlier in the driver, so let's move it next to the other
scrambling-related helpers.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d385003d7f42..a510da7462fd 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -124,6 +124,23 @@ static unsigned long long
 vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
unsigned int bpc, enum 
vc4_hdmi_output_format fmt);
 
+static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder)
+{
+   struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+   struct drm_display_info *display = &vc4_hdmi->connector.display_info;
+
+   lockdep_assert_held(&vc4_hdmi->mutex);
+
+   if (!display->is_hdmi)
+   return false;
+
+   if (!display->hdmi.scdc.supported ||
+   !display->hdmi.scdc.scrambling.supported)
+   return false;
+
+   return true;
+}
+
 static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
   unsigned int bpc,
   enum vc4_hdmi_output_format fmt)
@@ -742,23 +759,6 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder 
*encoder)
vc4_hdmi_set_hdr_infoframe(encoder);
 }
 
-static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder)
-{
-   struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-   struct drm_display_info *display = &vc4_hdmi->connector.display_info;
-
-   lockdep_assert_held(&vc4_hdmi->mutex);
-
-   if (!display->is_hdmi)
-   return false;
-
-   if (!display->hdmi.scdc.supported ||
-   !display->hdmi.scdc.scrambling.supported)
-   return false;
-
-   return true;
-}
-
 #define SCRAMBLING_POLLING_DELAY_MS1000
 
 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
-- 
2.37.1



[PATCH v4 7/8] drm/vc4: hdmi: Reset link on hotplug

2022-08-29 Thread Maxime Ripard
During a hotplug cycle (such as a TV going out of suspend, or when the
cable is disconnected and reconnected), the expectation is that the same
state used before the disconnection is reused until the next commit.

However, the HDMI scrambling requires that some flags are set in the
monitor, and those flags are very likely to be reset when the cable has
been disconnected. This will thus result in a blank display, even if the
display pipeline configuration hasn't been modified or is in the exact
same state.

The solution we've had so far is to enable the scrambling-related bits
again on reconnection, but the HDMI 2.0 specification (Section 6.1.3.1 -
Scrambling Control) requires that the scrambling enable bit is set
before sending any scrambled video signal. Using that solution thus
breaks that expectation.

The solution used by i915 is to do a full modeset on the connector so
that we disable the video signal, enable the scrambling bit, and enable
the video signal again.

As such, we took that code and plugged it into vc4. It probably could
have been turned into an helper, but it proved to be difficult for
several reasons:

  * i915 has fairly different structures than simpler KMS drivers such
as vc4, so doing some code that works with both proved to be
difficult;

  * Other simpler drivers could reuse some of it (tegra, dw-hdmi), but
it would still require to move some parameters currently stored in
private structure that are needed to compute whether the scrambling
is needed or not, and then inform the driver that it needs to be
enabled. Some of those parameters are already in core structures
(drm_display_mode, drm_display_info, bpc), but the output format
isnt't. Adding it is fairly challenging since unlike the TMDS char
rate or mode, there's no consensus on what format to pick in
drivers, so it's not possible to write some generic code that can
depend on it.

For these reasons, we chose to duplicate the code for now, until someone
else really needs it as well, in which case we will be able to convert
it into a generic helper.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 104 -
 1 file changed, 101 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a510da7462fd..1b3131947a5b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -288,9 +288,103 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi 
*vc4_hdmi)
 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
 #endif
 
-static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder);
+static int reset_pipe(struct drm_crtc *crtc,
+   struct drm_modeset_acquire_ctx *ctx)
+{
+   struct drm_atomic_state *state;
+   struct drm_crtc_state *crtc_state;
+   int ret;
+
+   state = drm_atomic_state_alloc(crtc->dev);
+   if (!state)
+   return -ENOMEM;
+
+   state->acquire_ctx = ctx;
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR(crtc_state)) {
+   ret = PTR_ERR(crtc_state);
+   goto out;
+   }
+
+   crtc_state->connectors_changed = true;
+
+   ret = drm_atomic_commit(state);
+out:
+   drm_atomic_state_put(state);
+
+   return ret;
+}
+
+static int vc4_hdmi_reset_link(struct drm_connector *connector,
+  struct drm_modeset_acquire_ctx *ctx)
+{
+   struct drm_device *drm = connector->dev;
+   struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+   struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+   bool scrambling_needed;
+   u8 config;
+   int ret;
+
+   if (!connector)
+   return 0;
+
+   ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx);
+   if (ret)
+   return ret;
+
+   conn_state = connector->state;
+   crtc = conn_state->crtc;
+   if (!crtc)
+   return 0;
+
+   ret = drm_modeset_lock(&crtc->mutex, ctx);
+   if (ret)
+   return ret;
+
+   crtc_state = crtc->state;
+   if (!crtc_state->active)
+   return 0;
+
+   if (!vc4_hdmi_supports_scrambling(encoder))
+   return 0;
+
+   scrambling_needed = 
vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode,
+  vc4_hdmi->output_bpc,
+  
vc4_hdmi->output_format);
+   if (!scrambling_needed)
+   return 0;
+
+   if (conn_state->commit &&
+   !try_wait_for_completion(&conn_state->commit->hw_done))
+   return 0;
+
+   ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config);
+   if (ret <

[PATCH v4 8/8] drm/scdc: Document hotplug gotchas

2022-08-29 Thread Maxime Ripard
There's some interactions between the SCDC setup and the disconnection /
reconnection of displays. Let's document it and a solution.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_scdc_helper.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c 
b/drivers/gpu/drm/display/drm_scdc_helper.c
index 81881e81ceae..c3ad4ab2b456 100644
--- a/drivers/gpu/drm/display/drm_scdc_helper.c
+++ b/drivers/gpu/drm/display/drm_scdc_helper.c
@@ -35,6 +35,19 @@
  * HDMI 2.0 specification. It is a point-to-point protocol that allows the
  * HDMI source and HDMI sink to exchange data. The same I2C interface that
  * is used to access EDID serves as the transport mechanism for SCDC.
+ *
+ * Note: The SCDC status is going to be lost when the display is
+ * disconnected. This can happen physically when the user disconnects
+ * the cable, but also when a display is switched on (such as waking up
+ * a TV).
+ *
+ * This is further complicated by the fact that, upon a disconnection /
+ * reconnection, KMS won't change the mode on its own. This means that
+ * one can't just rely on setting the SCDC status on enable, but also
+ * has to track the connector status changes using interrupts and
+ * restore the SCDC status. The typical solution for this is to trigger an
+ * empty modeset in drm_connector_helper_funcs.detect_ctx(), like what vc4 does
+ * in vc4_hdmi_reset_link().
  */
 
 #define SCDC_I2C_SLAVE_ADDRESS 0x54
-- 
2.37.1



Re: [PATCH v4,2/2] drm: mediatek: Adjust the dpi output format to MT8186

2022-08-29 Thread Nícolas F . R . A . Prado
On Mon, Aug 29, 2022 at 11:21:48AM +0800, xinlei@mediatek.com wrote:
> From: Xinlei Lee 
> 
> Dpi output needs to adjust the output format to dual edge for MT8186.
> 
> Co-developed-by: Jitao Shi 
> Signed-off-by: Jitao Shi 
> Signed-off-by: Xinlei Lee 

Reviewed-by: Nícolas F. R. A. Prado 

Thanks,
Nícolas


[PATCH 4/4] drm/i915: Extract drm_dp_atomic_find_vcpi_slots cycle to separate function

2022-08-29 Thread Stanislav Lisovskiy
We are using almost same code to loop through bpps while calling
drm_dp_atomic_find_vcpi_slots - lets remove this duplication by
introducing a new function intel_dp_mst_find_vcpi_slots_for_bpp

v2: Fix pbn_div calculation - shouldn't matter if its DSC or not.

Signed-off-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 86 +++--
 1 file changed, 45 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 94d7e7f84c51..7dcbdcd1cb48 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -44,10 +44,14 @@
 #include "intel_hotplug.h"
 #include "skl_scaler.h"
 
-static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
-   struct intel_crtc_state *crtc_state,
-   struct drm_connector_state 
*conn_state,
-   struct link_config_limits *limits)
+static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
+   struct intel_crtc_state 
*crtc_state,
+   int max_bpp,
+   int min_bpp,
+   struct link_config_limits 
*limits,
+   struct drm_connector_state 
*conn_state,
+   int step,
+   bool dsc)
 {
struct drm_atomic_state *state = crtc_state->uapi.state;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
@@ -58,7 +62,6 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
-   bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL;
int ret = 0;
 
@@ -72,18 +75,20 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
// TODO: Handle pbn_div changes by adding a new MST helper
if (!mst_state->pbn_div) {
mst_state->pbn_div = 
drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
- limits->max_rate,
- 
limits->max_lane_count);
+ 
crtc_state->port_clock,
+ 
crtc_state->lane_count);
}
 
-   for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
+   for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp,
-  false);
+  dsc ? bpp << 4 : 
crtc_state->pipe_bpp,
+  dsc);
+
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
- connector->port, 
crtc_state->pbn);
+ connector->port,
+ crtc_state->pbn);
if (slots == -EDEADLK)
return slots;
if (slots >= 0) {
@@ -101,11 +106,32 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
if (ret && slots >= 0)
slots = ret;
 
-   if (slots < 0) {
+   if (slots < 0)
drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",
slots);
+
+   return slots;
+}
+
+
+static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state 
*conn_state,
+   struct link_config_limits *limits)
+{
+   const struct drm_display_mode *adjusted_mode =
+   &crtc_state->hw.adjusted_mode;
+   struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
+   struct intel_dp *intel_dp = &intel_mst->primary->dp;
+   bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
DP_DPCD_QUIRK_CONSTANT_N);
+   int slots = -EINVAL;
+
+   slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, 
limits->max_bpp,
+limits->min_bpp

Re: [PATCH 1/5] drm/bridge: anx7625: Drop of_gpio header

2022-08-29 Thread Robert Foss
Hi Maira,

On Fri, 12 Aug 2022 at 22:58, Maíra Canal  wrote:
>
> This driver includes the deprecated OF GPIO header 
> yet fail to use symbols from it, so drop the include.
>
> Cc: Andrzej Hajda 
> Cc: Neil Armstrong 
> Cc: Robert Foss 
> Cc: Laurent Pinchart 
> Cc: Jonas Karlman 
> Cc: Jernej Skrabec 
> Signed-off-by: Maíra Canal 
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 79fc7a50b497..d7d4ca1c8b30 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -17,7 +17,6 @@
>  #include 
>  #include 
>
> -#include 
>  #include 
>  #include 
>
> --
> 2.37.1
>

This cleanup looks good to me.

Reviewed-by: Robert Foss 


Re: [PATCH] drm/bridge: anx7625: Support HDMI_I2S audio format

2022-08-29 Thread Robert Foss
On Wed, 10 Aug 2022 at 10:58, Hsin-Yi Wang  wrote:
>
> On Tue, Jul 26, 2022 at 5:16 PM Jiaxin Yu  wrote:
> >
> > On Tue, 2022-07-26 at 11:30 +0800, Xin Ji wrote:
> > > 1. Support HDMI_I2S audio format.
> > > 2. Return 0 if there is no sink connection in .hw_param callback.
> > >
> > > Signed-off-by: Xin Ji 
> > > ---
> > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 23 +--
> > > 
> > >  1 file changed, 17 insertions(+), 6 deletions(-)
> > >
> > Acked-by: Jiaxin Yu
> Acked-by: Hsin-Yi Wang 
>
> > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > index 79fc7a50b497..c74b5df4cade 100644
> > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > @@ -1797,8 +1797,13 @@ static int anx7625_audio_hw_params(struct
> > > device *dev, void *data,
> > >   int wl, ch, rate;
> > >   int ret = 0;
> > >
> > > - if (fmt->fmt != HDMI_DSP_A) {
> > > - DRM_DEV_ERROR(dev, "only supports DSP_A\n");
> > > + if (anx7625_sink_detect(ctx) == connector_status_disconnected)
> > > {
> > > + DRM_DEV_DEBUG_DRIVER(dev, "DP not connected\n");
> > > + return 0;
> > > + }
> > > +
> > > + if (fmt->fmt != HDMI_DSP_A && fmt->fmt != HDMI_I2S) {
> > > + DRM_DEV_ERROR(dev, "only supports DSP_A & I2S\n");
> > >   return -EINVAL;
> > >   }
> > >
> > > @@ -1806,10 +1811,16 @@ static int anx7625_audio_hw_params(struct
> > > device *dev, void *data,
> > >params->sample_rate, params->sample_width,
> > >params->cea.channels);
> > >
> > > - ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> > > - AUDIO_CHANNEL_STATUS_6,
> > > - ~I2S_SLAVE_MODE,
> > > - TDM_SLAVE_MODE);
> > > + if (fmt->fmt == HDMI_DSP_A)
> > > + ret = anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> > > +AUDIO_CHANNEL_STATUS_6,
> > > +~I2S_SLAVE_MODE,
> > > +TDM_SLAVE_MODE);
> > > + else
> > > + ret = anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> > > +AUDIO_CHANNEL_STATUS_6,
> > > +~TDM_SLAVE_MODE,
> > > +I2S_SLAVE_MODE);
> > >
> > >   /* Word length */
> > >   switch (params->sample_width) {
> >

Applied to drm-misc-next.


Re: [PATCH] drm/i915: fix repeated words in comments

2022-08-29 Thread Jani Nikula
On Tue, 23 Aug 2022, wangjianli  wrote:
>  Delete the redundant word 'the'.
>
> Signed-off-by: wangjianli 

Already fixed by commit 78f48aa6f50b ("drm/i915/irq: Fix a "the the"
typo").

What is this sudden influx of patches fixing repeated words everywhere?

BR,
Jani.


> ---
>  drivers/gpu/drm/i915/i915_irq.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 73cebc6aa650..783a6ca41a61 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -65,7 +65,7 @@
>  
>  /*
>   * Interrupt statistic for PMU. Increments the counter only if the
> - * interrupt originated from the the GPU so interrupts from a device which
> + * interrupt originated from the GPU so interrupts from a device which
>   * shares the interrupt line are not accounted.
>   */
>  static inline void pmu_irq_stats(struct drm_i915_private *i915,

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH v1 04/35] drm/modes: Introduce 480i and 576i modes

2022-08-29 Thread Geert Uytterhoeven
Hi Maxime,

On Mon, Aug 29, 2022 at 3:30 PM Maxime Ripard  wrote:
> On Wed, Aug 24, 2022 at 06:42:18PM +0200, Mateusz Kwiatkowski wrote:
> > - Speaking of closed captioning... a lot of different stuff were put in the
> >   blanking interval over the years. Like teletext in Europe. There are 
> > projects
> >   like VBIT2  which intentionally
> >   reconfigure the Raspberry Pi composite output to include the blanking 
> > interval
> >   in the framebuffer so that teletext can be output by drawing on the edge 
> > of
> >   the "screen" (from the computer point of view).
>
> I'm not sure how we would support this in KMS to be honest. Asking for a
> wider mode and the userspace putting whatever it wants in the margins
> seems like a good choice.

s/wider/higher/

Teletext is transmitted in the "visible" parts of (horizontal) lines, but during
the vertical blank.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH v3 03/14] gpu: drm: simplify drivers using devm_regulator_*get_enable*()

2022-08-29 Thread Robert Foss
Hi Matti,

On Fri, 19 Aug 2022 at 21:18, Matti Vaittinen  wrote:
>
> Simplify drivers using managed "regulator get and enable".
>
> meson:
> Use the devm_regulator_get_enable_optional(). Also drop the seemingly
> unused struct member 'hdmi_supply'.
>
> sii902x:
> Simplify using devm_regulator_bulk_get_enable()
>
> Signed-off-by: Matti Vaittinen 
>
> ---
> v2 => v3:
> No changes
>
> RFCv1 => v2:
> - Change also sii902x to use devm_regulator_bulk_get_enable()
>
> Please note - this is only compile-tested due to the lack of HW. Careful
> review and testing is _highly_ appreciated.
> ---
>  drivers/gpu/drm/bridge/sii902x.c  | 22 +++---
>  drivers/gpu/drm/meson/meson_dw_hdmi.c | 23 +++
>  2 files changed, 6 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/sii902x.c 
> b/drivers/gpu/drm/bridge/sii902x.c
> index 7ab38d734ad6..162f9c87eeb2 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -171,7 +171,6 @@ struct sii902x {
> struct drm_connector connector;
> struct gpio_desc *reset_gpio;
> struct i2c_mux_core *i2cmux;
> -   struct regulator_bulk_data supplies[2];
> bool sink_is_hdmi;
> /*
>  * Mutex protects audio and video functions from interfering
> @@ -1072,6 +1071,7 @@ static int sii902x_probe(struct i2c_client *client,
> struct device *dev = &client->dev;
> struct device_node *endpoint;
> struct sii902x *sii902x;
> +   static const char * const supplies[] = {"iovcc", "cvcc12"};
> int ret;
>
> ret = i2c_check_functionality(client->adapter,
> @@ -1122,27 +1122,13 @@ static int sii902x_probe(struct i2c_client *client,
>
> mutex_init(&sii902x->mutex);
>
> -   sii902x->supplies[0].supply = "iovcc";
> -   sii902x->supplies[1].supply = "cvcc12";
> -   ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sii902x->supplies),
> - sii902x->supplies);
> -   if (ret < 0)
> -   return ret;
> -
> -   ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
> -   sii902x->supplies);
> +   ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(supplies), 
> supplies);
> if (ret < 0) {
> dev_err_probe(dev, ret, "Failed to enable supplies");
> return ret;
> }
>
> -   ret = sii902x_init(sii902x);
> -   if (ret < 0) {
> -   regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
> -  sii902x->supplies);
> -   }
> -
> -   return ret;
> +   return sii902x_init(sii902x);
>  }
>
>  static int sii902x_remove(struct i2c_client *client)
> @@ -1152,8 +1138,6 @@ static int sii902x_remove(struct i2c_client *client)
>
> i2c_mux_del_adapters(sii902x->i2cmux);
> drm_bridge_remove(&sii902x->bridge);
> -   regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
> -  sii902x->supplies);
>
> return 0;
>  }

Ideally this patch would be split into two parts here, due to
maintainership boundaries.

For the sii902x part, please add my r-b.

Reviewed-by: Robert Foss 

> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c 
> b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> index 5cd2b2ebbbd3..7642f740272b 100644
> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> @@ -140,7 +140,6 @@ struct meson_dw_hdmi {
> struct reset_control *hdmitx_apb;
> struct reset_control *hdmitx_ctrl;
> struct reset_control *hdmitx_phy;
> -   struct regulator *hdmi_supply;
> u32 irq_stat;
> struct dw_hdmi *hdmi;
> struct drm_bridge *bridge;
> @@ -665,11 +664,6 @@ static void meson_dw_hdmi_init(struct meson_dw_hdmi 
> *meson_dw_hdmi)
>
>  }
>
> -static void meson_disable_regulator(void *data)
> -{
> -   regulator_disable(data);
> -}
> -
>  static void meson_disable_clk(void *data)
>  {
> clk_disable_unprepare(data);
> @@ -723,20 +717,9 @@ static int meson_dw_hdmi_bind(struct device *dev, struct 
> device *master,
> meson_dw_hdmi->data = match;
> dw_plat_data = &meson_dw_hdmi->dw_plat_data;
>
> -   meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
> -   if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
> -   if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
> -   return -EPROBE_DEFER;
> -   meson_dw_hdmi->hdmi_supply = NULL;
> -   } else {
> -   ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
> -   if (ret)
> -   return ret;
> -   ret = devm_add_action_or_reset(dev, meson_disable_regulator,
> -  meson_dw_hdmi->hdmi_supply);
> -   if (ret)
> -   return ret;
> -   }
> +   ret = devm_reg

Re: [PATCH] drm/i915: fix repeated words in comments

2022-08-29 Thread Jani Nikula
On Tue, 23 Aug 2022, Jilin Yuan  wrote:
>  Delete the redundant word 'other'.
>  Delete the redundant word 'the'.
>  Delete the redundant word 'will'.
>
> Signed-off-by: Jilin Yuan 

Doesn't apply because some of the hunks were already fixed by other
commits.

BR,
Jani.


> ---
>  drivers/gpu/drm/i915/i915_gem_evict.c | 2 +-
>  drivers/gpu/drm/i915/i915_irq.c   | 4 ++--
>  drivers/gpu/drm/i915/i915_memcpy.h| 2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c 
> b/drivers/gpu/drm/i915/i915_gem_evict.c
> index f025ee4fa526..028e509e1628 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -256,7 +256,7 @@ i915_gem_evict_something(struct i915_address_space *vm,
>   goto search_again;
>  
>  found:
> - /* drm_mm doesn't allow any other other operations while
> + /* drm_mm doesn't allow any other operations while
>* scanning, therefore store to-be-evicted objects on a
>* temporary list and take a reference for all before
>* calling unbind (which may remove the active reference
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 73cebc6aa650..1e4a705bc5cc 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -65,7 +65,7 @@
>  
>  /*
>   * Interrupt statistic for PMU. Increments the counter only if the
> - * interrupt originated from the the GPU so interrupts from a device which
> + * interrupt originated from the GPU so interrupts from a device which
>   * shares the interrupt line are not accounted.
>   */
>  static inline void pmu_irq_stats(struct drm_i915_private *i915,
> @@ -2175,7 +2175,7 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg)
>   raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
>  
>   /* Disable south interrupts. We'll only write to SDEIIR once, so further
> -  * interrupts will will be stored on its back queue, and then we'll be
> +  * interrupts will be stored on its back queue, and then we'll be
>* able to process them after we restore SDEIER (as soon as we restore
>* it, we'll get an interrupt if SDEIIR still has something to process
>* due to its back queue). */
> diff --git a/drivers/gpu/drm/i915/i915_memcpy.h 
> b/drivers/gpu/drm/i915/i915_memcpy.h
> index 3df063a3293b..126dfb4352f0 100644
> --- a/drivers/gpu/drm/i915/i915_memcpy.h
> +++ b/drivers/gpu/drm/i915/i915_memcpy.h
> @@ -18,7 +18,7 @@ void i915_unaligned_memcpy_from_wc(void *dst, const void 
> *src, unsigned long len
>  /* The movntdqa instructions used for memcpy-from-wc require 16-byte 
> alignment,
>   * as well as SSE4.1 support. i915_memcpy_from_wc() will report if it cannot
>   * perform the operation. To check beforehand, pass in the parameters to
> - * to i915_can_memcpy_from_wc() - since we only care about the low 4 bits,
> + * i915_can_memcpy_from_wc() - since we only care about the low 4 bits,
>   * you only need to pass in the minor offsets, page-aligned pointers are
>   * always valid.
>   *

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH 2/4] drm/i915: Fix intel_dp_mst_compute_link_config

2022-08-29 Thread Govindapillai, Vinod
Reviewed-by: Vinod Govindapillai 


On Mon, 2022-08-29 at 12:58 +0300, Stanislav Lisovskiy wrote:
> We currently always exit that bpp loop because drm_dp_atomic_find_vcpi_slots
> doesn't care if we actually can fit those or not.
> I think that wasn't the initial intention here, especially when
> we keep trying with lower bpps, we are supposed to keep trying
> until we actually find some _working_ configuration, which isn't the
> case here.
> So added that drm_dp_mst_check here, so that we can make sure
> that try all the bpps before we fail.
> 
> Signed-off-by: Stanislav Lisovskiy 
> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 13abe2b2170e..c4f92edbdd08 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -60,6 +60,7 @@ static int intel_dp_mst_compute_link_config(struct 
> intel_encoder *encoder,
> &crtc_state->hw.adjusted_mode;
> bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 
> DP_DPCD_QUIRK_CONSTANT_N);
> int bpp, slots = -EINVAL;
> +   int ret = 0;
>  
> mst_state = drm_atomic_get_mst_topology_state(state, 
> &intel_dp->mst_mgr);
> if (IS_ERR(mst_state))
> @@ -85,10 +86,21 @@ static int intel_dp_mst_compute_link_config(struct 
> intel_encoder *encoder,
>   connector->port, 
> crtc_state->pbn);
> if (slots == -EDEADLK)
> return slots;
> -   if (slots >= 0)
> -   break;
> +   if (slots >= 0) {
> +   ret = drm_dp_mst_atomic_check(state);
> +   /*
> +    * If we got slots >= 0 and we can fit those based on 
> check
> +    * then we can exit the loop. Otherwise keep trying.
> +    */
> +   if (!ret)
> +   break;
> +   }
> }
>  
> +   /* Despite slots are non-zero, we still failed the atomic check */
> +   if (ret && slots >= 0)
> +   slots = ret;
> +
> if (slots < 0) {
> drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",
>     slots);



Re: [PATCH v1 04/35] drm/modes: Introduce 480i and 576i modes

2022-08-29 Thread Maxime Ripard
On Mon, Aug 29, 2022 at 04:14:54PM +0200, Geert Uytterhoeven wrote:
> Hi Maxime,
> 
> On Mon, Aug 29, 2022 at 3:30 PM Maxime Ripard  wrote:
> > On Wed, Aug 24, 2022 at 06:42:18PM +0200, Mateusz Kwiatkowski wrote:
> > > - Speaking of closed captioning... a lot of different stuff were put in 
> > > the
> > >   blanking interval over the years. Like teletext in Europe. There are 
> > > projects
> > >   like VBIT2  which intentionally
> > >   reconfigure the Raspberry Pi composite output to include the blanking 
> > > interval
> > >   in the framebuffer so that teletext can be output by drawing on the 
> > > edge of
> > >   the "screen" (from the computer point of view).
> >
> > I'm not sure how we would support this in KMS to be honest. Asking for a
> > wider mode and the userspace putting whatever it wants in the margins
> > seems like a good choice.
> 
> s/wider/higher/
> 
> Teletext is transmitted in the "visible" parts of (horizontal) lines, but 
> during
> the vertical blank.

Yeah, sorry I meant wider as in larger than the active area, without any
direction in mind. Thanks for the correction :)

Maxime


signature.asc
Description: PGP signature


[PATCH] drm/amd/amdgpu: Add modeset module parameter support

2022-08-29 Thread Zhen Ni
Nomodeset kernel parameter is for all graphics cards. Amdgpu cannot
be set separately in some scenarios, such as hybrid graphics(i + a).
Add modeset module parameter for amdgpu to set kernel mode separately.

Signed-off-by: Zhen Ni 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 429fcdf28836..856a70370e3c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -107,6 +107,7 @@
 #define KMS_DRIVER_MINOR   48
 #define KMS_DRIVER_PATCHLEVEL  0
 
+int amdgpu_modeset = -1;
 int amdgpu_vram_limit;
 int amdgpu_vis_vram_limit;
 int amdgpu_gart_size = -1; /* auto */
@@ -199,6 +200,13 @@ struct amdgpu_watchdog_timer amdgpu_watchdog_timer = {
.period = 0x0, /* default to 0x0 (timeout disable) */
 };
 
+/**
+ * DOC: modeset (int)
+ * Disable/Enable kernel modesetting (1 = enable, 0 = disable, -1 = auto 
(default)).
+ */
+MODULE_PARM_DESC(modeset, "Disable/Enable kernel modesetting");
+module_param_named(modeset, amdgpu_modeset, int, 0400);
+
 /**
  * DOC: vramlimit (int)
  * Restrict the total amount of VRAM in MiB for testing.  The default is 0 
(Use full VRAM).
@@ -2753,7 +2761,10 @@ static int __init amdgpu_init(void)
 {
int r;
 
-   if (drm_firmware_drivers_only())
+   if (drm_firmware_drivers_only() && amdgpu_modeset == -1)
+   amdgpu_modeset = 0;
+
+   if (amdgpu_modeset == 0)
return -EINVAL;
 
r = amdgpu_sync_init();
-- 
2.20.1



  1   2   >