Re: [PATCH] drm: lcdif: Set and enable FIFO Panic threshold

2022-10-26 Thread Liu Ying
Hi,

On Wed, 2022-10-26 at 23:20 +0200, Marek Vasut wrote:
> In case the LCDIFv3 is used to drive a 4k panel via i.MX8MP HDMI bridge,
> the LCDIFv3 becomes susceptible to FIFO underflows, which lead to nasty

s/lead/leads/

> flicker of the image on the panel, or image being shifted by half frame
> horizontally every second frame. The flicker can be easily triggered by
> running 3D application on top of weston compositor, like neverball or
> chromium. Surprisingly glmark2-es2-wayland or glmark2-es2-drm does not
> trigger this effect so easily.
> 
> Configure the FIFO Panic threshold register and enable the FIFO Panic
> mode, which internally boosts the NoC interconnect priority for LCDIFv3
> transactions in case of possible underflow. This mitigates the flicker
> effect on 4k panels as well.
> 
> Fixes: 9db35bb349a0 ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
> Signed-off-by: Marek Vasut 
> ---
> Cc: Kieran Bingham 
> Cc: Laurent Pinchart 
> Cc: Liu Ying 
> Cc: Lucas Stach 
> Cc: Marco Felsch 
> Cc: Martyn Welch 
> Cc: Peng Fan 
> Cc: Sam Ravnborg 
> ---
>  drivers/gpu/drm/mxsfb/lcdif_kms.c  | 15 +++
>  drivers/gpu/drm/mxsfb/lcdif_regs.h |  1 +
>  2 files changed, 16 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
> b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> index a5302006c02cd..aee7babb5fa5c 100644
> --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> @@ -341,6 +341,18 @@ static void lcdif_enable_controller(struct 
> lcdif_drm_private *lcdif)
>   reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
>   reg |= CTRLDESCL0_5_EN;
>   writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
> +
> + /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
> + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_RANGE / 3) |
> +FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_RANGE / 3),

Better to define PANIC0_THRES_{LOW,HIGH}(n) macros in lcdif_regs.h?

Downstream kernel uses the below threshold values:
a) i.MX8mp EVK board with LPDDR4
1/3 and 2/3 for LCDIF{1,2} + DSI/LVDS - default values in driver
1/2 and 3/4 for LCDIF3 + HDMI - set in device tree

b) i.MX8mp EVK board with DDR4
1/3 and 2/3 for LCDIF{1,2} + DSI/LVDS - default values in driver
2/3 and 3/3 for LCDIF3 + HDMI - set in devic tree

Jian told me that LCDIF3 needs different sets of threshold values for
different types of DDR to avoid 4k HDMI display issues and the
threshold values impact overall DDR/bus utilization(?), so downstream
kernel chooses to get optional threshold value properties from LCDIF DT
node.

Instead of always using 1/3 and 2/3, maybe there are three options:
1) Same to downstream kernel, take 1/3 and 2/3 as default values and
get optional threshold values from DT properties - no additional
properties are acceptable in the existing DT binding doc?
2) Check pixel clock rate, and if it is greater than a certain value,
use 2/3 and 3/3.  Otherwise, use 1/3 and 2/3.
3) Always use 2/3 and 3/3.

> +lcdif->base + LCDC_V8_PANIC0_THRES);
> +
> + /*
> +  * Enable FIFO Panic, this does not generate interrupt, but
> +  * boosts NoC priority based on FIFO Panic watermarks.
> +  */
> + writel(INT_ENABLE_D1_PLANE_PANIC_EN,
> +lcdif->base + LCDC_V8_INT_ENABLE_D1);

This should be enabled _before_ LCDIF controller starts to fetch
pixels, otherwise, there is chance that the FIFO still underflows. 

>  }
>  
>  static void lcdif_disable_controller(struct lcdif_drm_private *lcdif)
> @@ -348,6 +360,9 @@ static void lcdif_disable_controller(struct 
> lcdif_drm_private *lcdif)
>   u32 reg;
>   int ret;
>  
> + /* Disable FIFO Panic NoC priority booster. */
> + writel(0, lcdif->base + LCDC_V8_INT_ENABLE_D1);

Similar to enablement, this should be disabled _after_ LCDIF controller
stops fetching pixels.

> +
>   reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
>   reg &= ~CTRLDESCL0_5_EN;
>   writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_regs.h 
> b/drivers/gpu/drm/mxsfb/lcdif_regs.h
> index fb74eb5ccbf1d..3d2f81d6f995e 100644
> --- a/drivers/gpu/drm/mxsfb/lcdif_regs.h
> +++ b/drivers/gpu/drm/mxsfb/lcdif_regs.h
> @@ -255,6 +255,7 @@
>  
>  #define PANIC0_THRES_LOW_MASKGENMASK(24, 16)
>  #define PANIC0_THRES_HIGH_MASK   GENMASK(8, 0)
> +#define PANIC0_THRES_RANGE   512

Should be 511? If high threshold is 3/3 and PANIC0_THRES_RANGE = 512,
PANIC0_THRES_HIGH will overflow and zero is set.

Regards,
Liu Ying

[...]



RE: [pull] amdgpu, amdkfd drm-fixes-6.1

2022-10-26 Thread Chen, Guchun
Hello Alex,

Regarding below patch, I guess we need to pick "8eb402f16d5b drm/amdgpu: Fix 
uninitialized warning in mmhub_v2_0_get_clockgating()" together, otherwise, 
build will possibly fail. Is it true?

 " Lijo Lazar (1): 
  drm/amdgpu: Remove ATC L2 access for MMHUB 2.1.x"

Regards,
Guchun

-Original Message-
From: amd-gfx  On Behalf Of Alex Deucher
Sent: Thursday, October 27, 2022 10:41 AM
To: amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; 
airl...@gmail.com; daniel.vet...@ffwll.ch
Cc: Deucher, Alexander 
Subject: [pull] amdgpu, amdkfd drm-fixes-6.1

Hi Dave, Daniel,

Fixes for 6.1.  Fixes for new IPs and misc other fixes.

The following changes since commit cbc543c59e8e7c8bc8604d6ac3e18a029e3d5118:

  Merge tag 'drm-misc-fixes-2022-10-20' of 
git://anongit.freedesktop.org/drm/drm-misc into drm-fixes (2022-10-21 09:56:14 
+1000)

are available in the Git repository at:

  
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.freedesktop.org%2Fagd5f%2Flinux.gitdata=05%7C01%7Cguchun.chen%40amd.com%7C6bbe7e42eb3d43bf622208dab7c4c906%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C638024353059986195%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=Y%2BU1OrPyhCaS44nGQMTrtqBpdkcJwFdFJEAaqWGiaqo%3Dreserved=0
 tags/amd-drm-fixes-6.1-2022-10-26-1

for you to fetch changes up to d61e1d1d5225a9baeb995bcbdb904f66f70ed87e:

  drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume 
(2022-10-26 17:48:43 -0400)


amd-drm-fixes-6.1-2022-10-26-1:

amdgpu:
- Stable pstate fix
- SMU 13.x updates
- SR-IOV fixes
- PCI AER fix
- GC 11.x fixes
- Display fixes
- Expose IMU firmware version for debugging
- Plane modifier fix
- S0i3 fix

amdkfd:
- Fix possible memory leak
- Fix GC 10.x cache info reporting

UAPI:
- Expose IMU firmware version via existing INFO firmware query


Alvin Lee (1):
  drm/amd/display: Don't return false if no stream

Chengming Gui (1):
  drm/amdgpu: fix pstate setting issue

David Francis (1):
  drm/amd: Add IMU fw version to fw version queries

Jesse Zhang (1):
  drm/amdkfd: correct the cache info for gfx1036

Joaquín Ignacio Aramendía (1):
  drm/amd/display: Revert logic for plane modifiers

Kenneth Feng (2):
  drm/amd/pm: update driver-if header for smu_v13_0_10
  drm/amd/pm: allow gfxoff on gc_11_0_3

Lijo Lazar (1):
  drm/amdgpu: Remove ATC L2 access for MMHUB 2.1.x

Prike Liang (2):
  drm/amdkfd: update gfx1037 Lx cache setting
  drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume

Rafael Mendonca (1):
  drm/amdkfd: Fix memory leak in kfd_mem_dmamap_userptr()

Rodrigo Siqueira (1):
  drm/amd/display: Remove wrong pipe control lock

Yiqing Yao (1):
  drm/amdgpu: Adjust MES polling timeout for sriov

YuBiao Wang (1):
  drm/amdgpu: skip mes self test for gc 11.0.3 in recover

 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   |   6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c|   5 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  18 +++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c|  13 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c  |   4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c   |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h|   1 +
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c |   1 +
 drivers/gpu/drm/amd/amdgpu/mes_v11_0.c |   9 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c|  28 ++
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c  | 106 +++-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c|  50 ++
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c |  12 +--
 .../amd/display/dc/dcn32/dcn32_resource_helpers.c  |   2 +-
 .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h | 111 +++--
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h   |   2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c |   7 +-
 include/uapi/drm/amdgpu_drm.h  |   2 +
 18 files changed, 259 insertions(+), 119 deletions(-)


Re: [PATCH v3] drm/i915/gvt: fix double free bug in split_2MB_gtt_entry

2022-10-26 Thread Dave Airlie
On Thu, 27 Oct 2022 at 13:26, Zheng Hacker  wrote:
>
> Dave Airlie  于2022年10月27日周四 08:01写道:
> >
> > On Fri, 7 Oct 2022 at 11:38, Zheng Wang  wrote:
> > >
> > > If intel_gvt_dma_map_guest_page failed, it will call
> > > ppgtt_invalidate_spt, which will finally free the spt.
> > > But the caller does not notice that, it will free spt again in error path.
> > >
> > > Fix this by spliting invalidate and free in ppgtt_invalidate_spt.
> > > Only free spt when in good case.
> > >
> > > Reported-by: Zheng Wang 
> > > Signed-off-by: Zheng Wang 
> >
> > Has this landed in a tree yet, since it's a possible CVE, might be
> > good to merge it somewhere.
> >
> > Dave.
> >
>
> Hi Dave,
>
> This patched hasn't been merged yet. Could you please help with this?

I'll add some more people who can probably look at it.

Dave.


Re: [PATCH v3] drm/i915/gvt: fix double free bug in split_2MB_gtt_entry

2022-10-26 Thread Zheng Hacker
Dave Airlie  于2022年10月27日周四 08:01写道:
>
> On Fri, 7 Oct 2022 at 11:38, Zheng Wang  wrote:
> >
> > If intel_gvt_dma_map_guest_page failed, it will call
> > ppgtt_invalidate_spt, which will finally free the spt.
> > But the caller does not notice that, it will free spt again in error path.
> >
> > Fix this by spliting invalidate and free in ppgtt_invalidate_spt.
> > Only free spt when in good case.
> >
> > Reported-by: Zheng Wang 
> > Signed-off-by: Zheng Wang 
>
> Has this landed in a tree yet, since it's a possible CVE, might be
> good to merge it somewhere.
>
> Dave.
>

Hi Dave,

This patched hasn't been merged yet. Could you please help with this?

Best Regards,
Zheng Wang


[PATCH] drm/bridge: it6505: Fix return value check for pm_runtime_get_sync

2022-10-26 Thread Pin-yen Lin
`pm_runtime_get_sync` may return 1 on success. Fix the `if` statement
here to make the code less confusing, even though additional calls to
`it6505_poweron` doesn't break anything when it's already powered.

This was reported by Dan Carpenter  in
https://lore.kernel.org/all/Y1fMCs6VnxbDcB41@kili/

Fixes: 1051d302 ("drm/bridge: it6505: Adapt runtime power management 
framework")
Signed-off-by: Pin-yen Lin 

---

 drivers/gpu/drm/bridge/ite-it6505.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index b929fc766e24..21a9b8422bda 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -2699,7 +2699,7 @@ static void it6505_extcon_work(struct work_struct *work)
 * pm_runtime_force_resume re-enables runtime power management.
 * Handling the error here to make sure the bridge is powered 
on.
 */
-   if (ret)
+   if (ret < 0)
it6505_poweron(it6505);
 
complete_all(>extcon_completion);
-- 
2.38.0.135.g90850a2211-goog



[PATCH v6 2/2] drm/bridge: add it6505 driver to read data-lanes and link-frequencies from dt

2022-10-26 Thread allen
From: allen chen 

Add driver to read data-lanes and link-frequencies from dt property to
restrict output bandwidth.

Signed-off-by: Allen chen 
Signed-off-by: Pin-yen Lin 
---
 drivers/gpu/drm/bridge/ite-it6505.c | 80 +++--
 1 file changed, 77 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index a4302492cf8df..ed4536cde3140 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -437,6 +437,8 @@ struct it6505 {
bool powered;
bool hpd_state;
u32 afe_setting;
+   u32 max_dpi_pixel_clock;
+   u32 max_lane_count;
enum hdcp_state hdcp_status;
struct delayed_work hdcp_work;
struct work_struct hdcp_wait_ksv_list;
@@ -1476,7 +1478,8 @@ static void it6505_parse_link_capabilities(struct it6505 
*it6505)
it6505->lane_count = link->num_lanes;
DRM_DEV_DEBUG_DRIVER(dev, "Sink support %d lanes training",
 it6505->lane_count);
-   it6505->lane_count = min_t(int, it6505->lane_count, MAX_LANE_COUNT);
+   it6505->lane_count = min_t(int, it6505->lane_count,
+  it6505->max_lane_count);
 
it6505->branch_device = drm_dp_is_branch(it6505->dpcd);
DRM_DEV_DEBUG_DRIVER(dev, "Sink %sbranch device",
@@ -2912,7 +2915,7 @@ it6505_bridge_mode_valid(struct drm_bridge *bridge,
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
return MODE_NO_INTERLACE;
 
-   if (mode->clock > DPI_PIXEL_CLK_MAX)
+   if (mode->clock > it6505->max_dpi_pixel_clock)
return MODE_CLOCK_HIGH;
 
it6505->video_info.clock = mode->clock;
@@ -3099,10 +3102,32 @@ static int it6505_init_pdata(struct it6505 *it6505)
return 0;
 }
 
+static int it6505_get_data_lanes_count(const struct device_node *endpoint,
+  const unsigned int min,
+  const unsigned int max)
+{
+   int ret;
+
+   ret = of_property_count_u32_elems(endpoint, "data-lanes");
+   if (ret < 0)
+   return ret;
+
+   if (ret < min || ret > max)
+   return -EINVAL;
+
+   return ret;
+}
+
 static void it6505_parse_dt(struct it6505 *it6505)
 {
struct device *dev = >client->dev;
+   struct device_node *np = dev->of_node, *ep = NULL;
+   int len;
+   u64 link_frequencies;
+   u32 data_lanes[4];
u32 *afe_setting = >afe_setting;
+   u32 *max_lane_count = >max_lane_count;
+   u32 *max_dpi_pixel_clock = >max_dpi_pixel_clock;
 
it6505->lane_swap_disabled =
device_property_read_bool(dev, "no-laneswap");
@@ -3118,7 +3143,56 @@ static void it6505_parse_dt(struct it6505 *it6505)
} else {
*afe_setting = 0;
}
-   DRM_DEV_DEBUG_DRIVER(dev, "using afe_setting: %d", *afe_setting);
+
+   ep = of_graph_get_endpoint_by_regs(np, 1, 0);
+   of_node_put(ep);
+
+   if (ep) {
+   len = it6505_get_data_lanes_count(ep, 1, 4);
+
+   if (len > 0 && len != 3) {
+   of_property_read_u32_array(ep, "data-lanes",
+  data_lanes, len);
+   *max_lane_count = len;
+   } else {
+   *max_lane_count = MAX_LANE_COUNT;
+   dev_err(dev, "error data-lanes, use default");
+   }
+   } else {
+   *max_lane_count = MAX_LANE_COUNT;
+   dev_err(dev, "error endpoint, use default");
+   }
+
+   ep = of_graph_get_endpoint_by_regs(np, 0, 0);
+   of_node_put(ep);
+
+   if (ep) {
+   len = of_property_read_variable_u64_array(ep,
+ "link-frequencies",
+ _frequencies, 0,
+ 1);
+   if (len >= 0) {
+   do_div(link_frequencies, 1000);
+   if (link_frequencies > 297000) {
+   dev_err(dev,
+   "max pixel clock error, use default");
+   *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX;
+   } else {
+   *max_dpi_pixel_clock = link_frequencies;
+   }
+   } else {
+   dev_err(dev, "error link frequencies, use default");
+   *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX;
+   }
+   } else {
+   dev_err(dev, "error endpoint, use default");
+   *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX;
+   }
+
+   DRM_DEV_DEBUG_DRIVER(dev, "using afe_setting: %u, max_lane_count: %u",
+it6505->afe_setting, 

[PATCH v6 1/2] dt-bindings: it6505: add properties to restrict output bandwidth

2022-10-26 Thread allen
From: allen chen 

Add properties to restrict dp output data-lanes and clock.

Signed-off-by: Pin-Yen Lin 
Signed-off-by: Allen Chen 
---
 .../bindings/display/bridge/ite,it6505.yaml   | 68 +--
 1 file changed, 62 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml 
b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
index 833d11b2303a7..b16a9d9127ddb 100644
--- a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
@@ -52,9 +52,49 @@ properties:
 maxItems: 1
 description: extcon specifier for the Power Delivery
 
-  port:
-$ref: /schemas/graph.yaml#/properties/port
-description: A port node pointing to DPI host port node
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/$defs/port-base
+unevaluatedProperties: false
+description: A port node pointing to DPI host port node
+
+properties:
+  endpoint:
+$ref: /schemas/graph.yaml#/$defs/endpoint-base
+unevaluatedProperties: false
+
+properties:
+  link-frequencies:
+minItems: 1
+maxItems: 1
+description: Allowed max link frequencies in Hz
+
+  port@1:
+$ref: /schemas/graph.yaml#/$defs/port-base
+unevaluatedProperties: false
+description: Video port for DP output
+
+properties:
+  endpoint:
+$ref: /schemas/graph.yaml#/$defs/endpoint-base
+unevaluatedProperties: false
+
+properties:
+  data-lanes:
+minItems: 1
+uniqueItems: true
+items:
+  - enum: [ 0, 1 ]
+  - const: 1
+  - const: 2
+  - const: 3
+
+required:
+  - port@0
+  - port@1
 
 required:
   - compatible
@@ -63,6 +103,7 @@ required:
   - interrupts
   - reset-gpios
   - extcon
+  - ports
 
 additionalProperties: false
 
@@ -85,9 +126,24 @@ examples:
 reset-gpios = < 179 1>;
 extcon = <_extcon>;
 
-port {
-it6505_in: endpoint {
-remote-endpoint = <_out>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+it6505_in: endpoint {
+remote-endpoint = <_out>;
+link-frequencies = /bits/ 64 <15000>;
+};
+};
+
+port@1 {
+reg = <1>;
+it6505_out: endpoint {
+remote-endpoint = <_in>;
+data-lanes = <0 1>;
+};
 };
 };
 };
-- 
2.25.1



Re: [PATCH v5 1/2] dt-bindings: it6505: add properties to restrict output bandwidth

2022-10-26 Thread Pin-yen Lin
Hi Allen,

On Thu, Oct 27, 2022 at 9:09 AM  wrote:
>
> Hi rob
>
> -Original Message-
> From: Rob Herring 
> Sent: Tuesday, October 25, 2022 12:38 AM
> To: Allen Chen (陳柏宇) 
> Cc: Pin-Yen Lin ; Jau-Chih Tseng (曾昭智) 
> ; Hermes Wu (吳佳宏) ; Kenneth 
> Hung (洪家倫) ; Andrzej Hajda 
> ; Neil Armstrong ; Robert 
> Foss ; Laurent Pinchart 
> ; Jonas Karlman ; Jernej 
> Skrabec ; David Airlie ; Daniel 
> Vetter ; Krzysztof Kozlowski 
> ; open list:DRM DRIVERS 
> ; open list:OPEN FIRMWARE AND FLATTENED 
> DEVICE TREE BINDINGS ; open list 
> 
> Subject: Re: [PATCH v5 1/2] dt-bindings: it6505: add properties to restrict 
> output bandwidth
>
> On Wed, Oct 19, 2022 at 05:32:13PM +0800, allen wrote:
> > From: allen chen 
> >
> > Add properties to restrict dp output data-lanes and clock.
> >
> > Signed-off-by: Pin-Yen Lin 
> > Signed-off-by: Allen Chen 
> > ---
> >  .../bindings/display/bridge/ite,it6505.yaml   | 89 +--
> >  1 file changed, 83 insertions(+), 6 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> > b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> > index 833d11b2303a7..8e607b6929fc9 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> > +++ b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> > @@ -52,9 +52,70 @@ properties:
> >  maxItems: 1
> >  description: extcon specifier for the Power Delivery
> >
> > -  port:
> > -$ref: /schemas/graph.yaml#/properties/port
> > -description: A port node pointing to DPI host port node
>
> No existing users you are breaking? The commit msg should explain.
>
> ==> There are no it6505 users in community.

I would say, currently there are no "upstream" users. So, no existing
users to break.

The term "community" is a bit vague and broad.

Regards,
Pin-yen

> > +  ports:
> > +$ref: /schemas/graph.yaml#/properties/ports
> > +
> > +properties:
> > +  port@0:
> > +$ref: /schemas/graph.yaml#/$defs/port-base
> > +unevaluatedProperties: false
> > +description: A port node pointing to DPI host port node
> > +
> > +properties:
> > +  endpoint:
> > +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> > +unevaluatedProperties: false
> > +
> > +properties:
> > +  link-frequencies:
> > +minItems: 1
> > +maxItems: 1
> > +description: Allowed max link frequencies in Hz
> > +
> > +  port@1:
> > +$ref: /schemas/graph.yaml#/$defs/port-base
> > +unevaluatedProperties: false
> > +description: Video port for DP output
> > +
> > +properties:
> > +  endpoint:
> > +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> > +unevaluatedProperties: false
> > +
> > +properties:
> > +  data-lanes:
> > +oneOf:
> > +  - minItems: 1
> > +maxItems: 1
> > +uniqueItems: true
> > +items:
> > +  enum:
> > +- 0
> > +- 1
> > +description: For one lane operation.
> > +
> > +  - minItems: 2
> > +maxItems: 2
> > +uniqueItems: true
> > +items:
> > +  enum:
> > +- 0
> > +- 1
> > +description: For two lanes operation.
> > +
> > +  - minItems: 4
> > +maxItems: 4
> > +uniqueItems: true
> > +items:
> > +  enum:
> > +- 0
> > +- 1
> > +- 2
> > +- 3
> > +description: For four lanes operation.
>
> I would do just:
>
> data-lanes:
>   minItems: 1
>   items:
> - enum: [ 0, 1 ]
> - const: 1
> - const: 2
> - const: 3
>
> It does allow 3 lanes, but I don't think that's a big deal. What it does 
> doesn't allow is any order and yours does.
>
> Rob


[PATCH v6 0/2] *** IT6505 driver read dt properties ***

2022-10-26 Thread allen
This series let driver can read properties from dt to restrict dp output
bandwidth.

Changes in v3:
-Rename property name.

Changes in v4:
-Use data-lanes and link-frequencies instead of "ite,dp-output-data-lane-count" 
and "ite,dp-output-max-pixel-clock-mhz".

Changes in v5:
-Add a port and a endpoint.
-Move data-lanes property to the output endpoint.

Changes in v6:
-Modified data-lanes description by suggestion.

allen chen (2):
  dt-bindings: it6505: add properties to restrict output bandwidth
  drm/bridge: add it6505 driver to read data-lanes and link-frequencies
from dt

 .../bindings/display/bridge/ite,it6505.yaml   | 68 ++--
 drivers/gpu/drm/bridge/ite-it6505.c   | 80 ++-
 2 files changed, 139 insertions(+), 9 deletions(-)

-- 
2.25.1



[pull] amdgpu, amdkfd drm-fixes-6.1

2022-10-26 Thread Alex Deucher
Hi Dave, Daniel,

Fixes for 6.1.  Fixes for new IPs and misc other fixes.

The following changes since commit cbc543c59e8e7c8bc8604d6ac3e18a029e3d5118:

  Merge tag 'drm-misc-fixes-2022-10-20' of 
git://anongit.freedesktop.org/drm/drm-misc into drm-fixes (2022-10-21 09:56:14 
+1000)

are available in the Git repository at:

  https://gitlab.freedesktop.org/agd5f/linux.git 
tags/amd-drm-fixes-6.1-2022-10-26-1

for you to fetch changes up to d61e1d1d5225a9baeb995bcbdb904f66f70ed87e:

  drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume 
(2022-10-26 17:48:43 -0400)


amd-drm-fixes-6.1-2022-10-26-1:

amdgpu:
- Stable pstate fix
- SMU 13.x updates
- SR-IOV fixes
- PCI AER fix
- GC 11.x fixes
- Display fixes
- Expose IMU firmware version for debugging
- Plane modifier fix
- S0i3 fix

amdkfd:
- Fix possible memory leak
- Fix GC 10.x cache info reporting

UAPI:
- Expose IMU firmware version via existing INFO firmware query


Alvin Lee (1):
  drm/amd/display: Don't return false if no stream

Chengming Gui (1):
  drm/amdgpu: fix pstate setting issue

David Francis (1):
  drm/amd: Add IMU fw version to fw version queries

Jesse Zhang (1):
  drm/amdkfd: correct the cache info for gfx1036

Joaquín Ignacio Aramendía (1):
  drm/amd/display: Revert logic for plane modifiers

Kenneth Feng (2):
  drm/amd/pm: update driver-if header for smu_v13_0_10
  drm/amd/pm: allow gfxoff on gc_11_0_3

Lijo Lazar (1):
  drm/amdgpu: Remove ATC L2 access for MMHUB 2.1.x

Prike Liang (2):
  drm/amdkfd: update gfx1037 Lx cache setting
  drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume

Rafael Mendonca (1):
  drm/amdkfd: Fix memory leak in kfd_mem_dmamap_userptr()

Rodrigo Siqueira (1):
  drm/amd/display: Remove wrong pipe control lock

Yiqing Yao (1):
  drm/amdgpu: Adjust MES polling timeout for sriov

YuBiao Wang (1):
  drm/amdgpu: skip mes self test for gc 11.0.3 in recover

 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   |   6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c|   5 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  18 +++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c|  13 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c  |   4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c   |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h|   1 +
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c |   1 +
 drivers/gpu/drm/amd/amdgpu/mes_v11_0.c |   9 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c|  28 ++
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c  | 106 +++-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c|  50 ++
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c |  12 +--
 .../amd/display/dc/dcn32/dcn32_resource_helpers.c  |   2 +-
 .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h | 111 +++--
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h   |   2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c |   7 +-
 include/uapi/drm/amdgpu_drm.h  |   2 +
 18 files changed, 259 insertions(+), 119 deletions(-)


Re: [PATCH v3 01/12] dt-bindings: display/msm: Add binding for SC8280XP MDSS

2022-10-26 Thread Bjorn Andersson
On Wed, Oct 26, 2022 at 12:54:41PM -0500, Rob Herring wrote:
> On Tue, Oct 25, 2022 at 08:26:13PM -0700, Bjorn Andersson wrote:
> > From: Bjorn Andersson 
> > 
> > Add binding for the display subsystem and display processing unit in the
> > Qualcomm SC8280XP platform.
> > 
> > Signed-off-by: Bjorn Andersson 
> > Signed-off-by: Bjorn Andersson 
> > ---
> > 
> > Changes since v2:
> > - Cleaned up description and interconnect definitions
> > - Added opp-table
> > 
> >  .../bindings/display/msm/dpu-sc8280xp.yaml| 287 ++
> >  1 file changed, 287 insertions(+)
> >  create mode 100644 
> > Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml
> 
> Doesn't this need to be reworked to match Dmitry's restructuring?
> 

I based my patches on linux-next, missed Dmitry's in-flight series.
Seems like this should be rebased on top of his series and hope it lands
soon.

Thanks,
Bjorn

> > 
> > diff --git 
> > a/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml 
> > b/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml
> > new file mode 100644
> > index ..24e7a1562fe7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml
> > @@ -0,0 +1,287 @@
> > +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/msm/dpu-sc8280xp.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Qualcomm Display Processing Unit for SC8280XP
> > +
> > +maintainers:
> > +  - Bjorn Andersson 
> > +
> > +description:
> > +  Device tree bindings for MSM Mobile Display Subsystem (MDSS) that 
> > encapsulates
> > +  sub-blocks like DPU display controller, DSI and DP interfaces etc.
> > +
> > +properties:
> > +  compatible:
> > +const: qcom,sc8280xp-mdss
> > +
> > +  reg:
> > +maxItems: 1
> > +
> > +  reg-names:
> > +const: mdss
> > +
> > +  power-domains:
> > +maxItems: 1
> > +
> > +  clocks:
> > +items:
> > +  - description: Display AHB clock from gcc
> > +  - description: Display AHB clock from dispcc
> > +  - description: Display core clock
> > +
> > +  clock-names:
> > +items:
> > +  - const: iface
> > +  - const: ahb
> > +  - const: core
> > +
> > +  interrupts:
> > +maxItems: 1
> > +
> > +  interrupt-controller: true
> > +
> 
> > +  "#address-cells": true
> > +
> > +  "#size-cells": true
> 
> enum: [ 1, 2 ]
> 
> (Nothing else sets that)
> 
> Rob


Re: [PATCH v3 12/12] arm64: dts: qcom: sa8295-adp: Enable DP instances

2022-10-26 Thread Bjorn Andersson
On Wed, Oct 26, 2022 at 01:50:15PM +0200, Johan Hovold wrote:
> On Tue, Oct 25, 2022 at 08:26:24PM -0700, Bjorn Andersson wrote:
> > From: Bjorn Andersson 
> > 
> > The SA8295P ADP has, among other interfaces, six MiniDP connectors which
> > are connected to MDSS0 DP2 and DP3, and MDSS1 DP0 through DP3.
> > 
> > Enable Display Clock controllers, MDSS instanced, MDPs, DP controllers,
> > DP PHYs and link them all together.
> > 
> > Signed-off-by: Bjorn Andersson 
> > Signed-off-by: Bjorn Andersson 
> > ---
> 
> >  _rsc {
> > @@ -156,13 +240,169 @@ vreg_l7g: ldo7 {
> >  
> > vreg_l8g: ldo8 {
> > regulator-name = "vreg_l8g";
> > -   regulator-min-microvolt = <88>;
> > -   regulator-max-microvolt = <88>;
> > +   regulator-min-microvolt = <912000>;
> > +   regulator-max-microvolt = <912000>;
> > +   regulator-initial-mode = ;
> > +   regulator-allow-set-load;
> 
> Did you really intend to allow set-load here?
> 
> I'm guessing this wasn't the case, but otherwise you also need to
> specify the valid modes.
> 

I see no reason for keeping it at this point in time, will drop it.

Thanks,
Bjorn

> > +   };
> > +
> > +   vreg_l11g: ldo11 {
> > +   regulator-name = "vreg_l11g";
> > +   regulator-min-microvolt = <912000>;
> > +   regulator-max-microvolt = <912000>;
> > regulator-initial-mode = ;
> > };
> > };
> >  };
> 
> > +_dp2_phy {
> > +   status = "okay";
> > +
> > +   vdda-phy-supply = <_l8g>;
> > +   vdda-pll-supply = <_l3g>;
> > +};
> 
> Johan


Re: [PATCH v3 09/12] drm/msm/dp: HPD handling relates to next_bridge

2022-10-26 Thread Bjorn Andersson
On Wed, Oct 26, 2022 at 09:08:49AM +0300, Dmitry Baryshkov wrote:
> 
> 
> On 26 October 2022 06:26:21 EEST, Bjorn Andersson  
> wrote:
> >From: Bjorn Andersson 
> >
> >The DisplayPort controller's internal HPD interrupt handling is used for
> >cases where the HPD signal is connected to a GPIO which is pinmuxed into
> >the DisplayPort controller.
> >
> >Most of the logic for enabling and disabling the HPD-related interrupts
> >is conditioned on the presence of an EDP panel, but more generically
> >designs that has a downstream drm_bridge (next_bridge) could use this to
> >handle the HPD interrupts, instead of the internal mechanism.
> >
> >So replace the current is_edp-based guards with a check for the presence
> >of next_bridge.
> 
> This does not sound correct. The next bridge might be a dummy bridge,
> not supporting the hpd.

I only considered checking for the Chrome case, where the output isn't
modelled and we have to rely on the internal HPD logic. Checking that
next_bridge is present and will deliver us hpd events sounds somewhat
reasonable.

But if I understand the code correctly, panel-edp isn't handing us hpd
events - and we still don't want the internal HPD logic to trigger. So I
presume I would need to check that this isn't a EDP controller and that
we're going to get external HPD events?

If so, clean you please give me some pointer on how to check if
next_bridge will provide us with hpd signaling or not?


PS. Which dummy bridge do you have in mind?

> Please change this to use the enable_hpd()/disable_hpd() callbacks.
> This way the drm_bridge_connector framework will make sure to enable
> hpd handling for the bridge that is actually supposed to generate hpd
> events.
> 

The drm_bridge_connector_init() call in dp_drm_connector_init() does
this for us already.

Regards,
Bjorn

> 
> >
> >Signed-off-by: Bjorn Andersson 
> >Signed-off-by: Bjorn Andersson 
> >---
> >
> >Changes since v2:
> >- None
> 
> 
> -- 
> With best wishes
> Dmitry


RE: [PATCH v5 1/2] dt-bindings: it6505: add properties to restrict output bandwidth

2022-10-26 Thread allen.chen
Hi rob

-Original Message-
From: Rob Herring  
Sent: Tuesday, October 25, 2022 12:38 AM
To: Allen Chen (陳柏宇) 
Cc: Pin-Yen Lin ; Jau-Chih Tseng (曾昭智) 
; Hermes Wu (吳佳宏) ; Kenneth 
Hung (洪家倫) ; Andrzej Hajda ; 
Neil Armstrong ; Robert Foss ; 
Laurent Pinchart ; Jonas Karlman 
; Jernej Skrabec ; David Airlie 
; Daniel Vetter ; Krzysztof Kozlowski 
; open list:DRM DRIVERS 
; open list:OPEN FIRMWARE AND FLATTENED DEVICE 
TREE BINDINGS ; open list 

Subject: Re: [PATCH v5 1/2] dt-bindings: it6505: add properties to restrict 
output bandwidth

On Wed, Oct 19, 2022 at 05:32:13PM +0800, allen wrote:
> From: allen chen 
> 
> Add properties to restrict dp output data-lanes and clock.
> 
> Signed-off-by: Pin-Yen Lin 
> Signed-off-by: Allen Chen 
> ---
>  .../bindings/display/bridge/ite,it6505.yaml   | 89 +--
>  1 file changed, 83 insertions(+), 6 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml 
> b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> index 833d11b2303a7..8e607b6929fc9 100644
> --- a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
> @@ -52,9 +52,70 @@ properties:
>  maxItems: 1
>  description: extcon specifier for the Power Delivery
>  
> -  port:
> -$ref: /schemas/graph.yaml#/properties/port
> -description: A port node pointing to DPI host port node

No existing users you are breaking? The commit msg should explain.

==> There are no it6505 users in community.
> +  ports:
> +$ref: /schemas/graph.yaml#/properties/ports
> +
> +properties:
> +  port@0:
> +$ref: /schemas/graph.yaml#/$defs/port-base
> +unevaluatedProperties: false
> +description: A port node pointing to DPI host port node
> +
> +properties:
> +  endpoint:
> +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> +unevaluatedProperties: false
> +
> +properties:
> +  link-frequencies:
> +minItems: 1
> +maxItems: 1
> +description: Allowed max link frequencies in Hz
> +
> +  port@1:
> +$ref: /schemas/graph.yaml#/$defs/port-base
> +unevaluatedProperties: false
> +description: Video port for DP output
> +
> +properties:
> +  endpoint:
> +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> +unevaluatedProperties: false
> +
> +properties:
> +  data-lanes:
> +oneOf:
> +  - minItems: 1
> +maxItems: 1
> +uniqueItems: true
> +items:
> +  enum:
> +- 0
> +- 1
> +description: For one lane operation.
> +
> +  - minItems: 2
> +maxItems: 2
> +uniqueItems: true
> +items:
> +  enum:
> +- 0
> +- 1
> +description: For two lanes operation.
> +
> +  - minItems: 4
> +maxItems: 4
> +uniqueItems: true
> +items:
> +  enum:
> +- 0
> +- 1
> +- 2
> +- 3
> +description: For four lanes operation.

I would do just:

data-lanes:
  minItems: 1
  items:
- enum: [ 0, 1 ]
- const: 1
- const: 2
- const: 3

It does allow 3 lanes, but I don't think that's a big deal. What it does 
doesn't allow is any order and yours does.

Rob


[PATCH] fbdev/core: Avoid uninitialized read in aperture_remove_conflicting_pci_device()

2022-10-26 Thread Michał Mirosław
Return on error directly from the BAR-iterating loop instead of
break+return.

This is actually a cosmetic fix, since it would be highly unusual to
have this called for a PCI device without any memory BARs.

Fixes: 9d69ef183815 ("fbdev/core: Remove remove_conflicting_pci_framebuffers()")
Signed-off-by: Michał Mirosław 
---
 drivers/video/aperture.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index 9e6bcc03a1a4..41e77de1ea82 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -340,12 +340,9 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev 
*pdev, const char *na
size = pci_resource_len(pdev, bar);
ret = aperture_remove_conflicting_devices(base, size, primary, 
name);
if (ret)
-   break;
+   return ret;
}
 
-   if (ret)
-   return ret;
-
/*
 * WARNING: Apparently we must kick fbdev drivers before vgacon,
 * otherwise the vga fbdev driver falls over.
-- 
2.30.2



Re: [PATCH v3] drm/i915/gvt: fix double free bug in split_2MB_gtt_entry

2022-10-26 Thread Dave Airlie
On Fri, 7 Oct 2022 at 11:38, Zheng Wang  wrote:
>
> If intel_gvt_dma_map_guest_page failed, it will call
> ppgtt_invalidate_spt, which will finally free the spt.
> But the caller does not notice that, it will free spt again in error path.
>
> Fix this by spliting invalidate and free in ppgtt_invalidate_spt.
> Only free spt when in good case.
>
> Reported-by: Zheng Wang 
> Signed-off-by: Zheng Wang 

Has this landed in a tree yet, since it's a possible CVE, might be
good to merge it somewhere.

Dave.

> ---
> v3:
> - correct spelling mistake and remove unused variable suggested by Greg
>
> v2: https://lore.kernel.org/all/20221006165845.1735393-1-zyytlz...@163.com/
>
> v1: https://lore.kernel.org/all/20220928033340.1063949-1-zyytlz...@163.com/
> ---
>  drivers/gpu/drm/i915/gvt/gtt.c | 32 +---
>  1 file changed, 21 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
> index ce0eb03709c3..865d33762e45 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.c
> +++ b/drivers/gpu/drm/i915/gvt/gtt.c
> @@ -959,6 +959,7 @@ static inline int ppgtt_put_spt(struct 
> intel_vgpu_ppgtt_spt *spt)
> return atomic_dec_return(>refcount);
>  }
>
> +static int ppgtt_invalidate_and_free_spt(struct intel_vgpu_ppgtt_spt *spt);
>  static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt);
>
>  static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
> @@ -995,7 +996,7 @@ static int ppgtt_invalidate_spt_by_shadow_entry(struct 
> intel_vgpu *vgpu,
> ops->get_pfn(e));
> return -ENXIO;
> }
> -   return ppgtt_invalidate_spt(s);
> +   return ppgtt_invalidate_and_free_spt(s);
>  }
>
>  static inline void ppgtt_invalidate_pte(struct intel_vgpu_ppgtt_spt *spt,
> @@ -1016,18 +1017,30 @@ static inline void ppgtt_invalidate_pte(struct 
> intel_vgpu_ppgtt_spt *spt,
> intel_gvt_dma_unmap_guest_page(vgpu, pfn << PAGE_SHIFT);
>  }
>
> -static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
> +static int ppgtt_invalidate_and_free_spt(struct intel_vgpu_ppgtt_spt *spt)
>  {
> -   struct intel_vgpu *vgpu = spt->vgpu;
> -   struct intel_gvt_gtt_entry e;
> -   unsigned long index;
> int ret;
>
> trace_spt_change(spt->vgpu->id, "die", spt,
> -   spt->guest_page.gfn, spt->shadow_page.type);
> -
> +   spt->guest_page.gfn, spt->shadow_page.type);
> if (ppgtt_put_spt(spt) > 0)
> return 0;
> +   ret = ppgtt_invalidate_spt(spt);
> +   if (!ret) {
> +   trace_spt_change(spt->vgpu->id, "release", spt,
> +spt->guest_page.gfn, spt->shadow_page.type);
> +   ppgtt_free_spt(spt);
> +   }
> +
> +   return ret;
> +}
> +
> +static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
> +{
> +   struct intel_vgpu *vgpu = spt->vgpu;
> +   struct intel_gvt_gtt_entry e;
> +   unsigned long index;
> +   int ret;
>
> for_each_present_shadow_entry(spt, , index) {
> switch (e.type) {
> @@ -1059,9 +1072,6 @@ static int ppgtt_invalidate_spt(struct 
> intel_vgpu_ppgtt_spt *spt)
> }
> }
>
> -   trace_spt_change(spt->vgpu->id, "release", spt,
> -spt->guest_page.gfn, spt->shadow_page.type);
> -   ppgtt_free_spt(spt);
> return 0;
>  fail:
> gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n",
> @@ -1393,7 +1403,7 @@ static int ppgtt_handle_guest_entry_removal(struct 
> intel_vgpu_ppgtt_spt *spt,
> ret = -ENXIO;
> goto fail;
> }
> -   ret = ppgtt_invalidate_spt(s);
> +   ret = ppgtt_invalidate_and_free_spt(s);
> if (ret)
> goto fail;
> } else {
> --
> 2.25.1
>


[PATCH v1 1/2] dma-buf: Make locking consistent in dma_buf_detach()

2022-10-26 Thread Dmitry Osipenko
The dma_buf_detach() locks attach->dmabuf->resv and then unlocks
dmabuf->resv, which could be a two different locks from a static
code checker perspective. In particular this triggers Smatch to
report the "double unlock" error. Make the locking pointers consistent.

Reported-by: Dan Carpenter 
Link: https://lore.kernel.org/dri-devel/Y1fLfsccW3AS%2Fo+%2F@kili/
Fixes: 809d9c72c2f8 ("dma-buf: Move dma_buf_attach() to dynamic locking 
specification")
Signed-off-by: Dmitry Osipenko 
---
 drivers/dma-buf/dma-buf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index c40d72d318fd..6e33ef4fde34 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -998,9 +998,10 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attach)
if (WARN_ON(!dmabuf || !attach))
return;
 
-   dma_resv_lock(attach->dmabuf->resv, NULL);
+   dma_resv_lock(dmabuf->resv, NULL);
 
if (attach->sgt) {
+   WARN_ON(dmabuf != attach->dmabuf);
 
__unmap_dma_buf(attach, attach->sgt, attach->dir);
 
-- 
2.37.3



[PATCH v1 2/2] drm/gem: Check whether object is NULL in drm_gem_vunmap()

2022-10-26 Thread Dmitry Osipenko
The drm_gem_vunmap() will crash with a NULL dereference if the passed
object pointer is NULL. It wasn't a problem before we added the locking
support to drm_gem_vunmap function because the mapping argument was always
NULL together with the object. Make drm_gem_vunmap() functions to handle
the NULL pointers better.

Reported-by: Dan Carpenter 
Link: https://lore.kernel.org/dri-devel/Y1kFEGxT8MVlf32V@kili/
Fixes: 79e2cf2e7a19 ("drm/gem: Take reservation lock for vmap/vunmap 
operations")
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index b8db675e7fb5..ee0a246ff4ac 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1175,11 +1175,11 @@ EXPORT_SYMBOL(drm_gem_vmap);
 
 void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
 {
-   dma_resv_assert_held(obj->resv);
-
-   if (iosys_map_is_null(map))
+   if (!obj || iosys_map_is_null(map))
return;
 
+   dma_resv_assert_held(obj->resv);
+
if (obj->funcs->vunmap)
obj->funcs->vunmap(obj, map);
 
@@ -1202,6 +1202,9 @@ EXPORT_SYMBOL(drm_gem_vmap_unlocked);
 
 void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map)
 {
+   if (!obj || iosys_map_is_null(map))
+   return;
+
dma_resv_lock(obj->resv, NULL);
drm_gem_vunmap(obj, map);
dma_resv_unlock(obj->resv);
-- 
2.37.3



[PATCH v1 0/2] Fixes for dma-buf locking issues found by Smatch

2022-10-26 Thread Dmitry Osipenko
Hello,

Here are the two patches fixing minor problems introduced by my
"dma-buf locking convention" series. Thanks to Dan Carpenter who
checked linux-next with Smatch and reported the found issues!

Please review/ack, I'll apply the patches to misc-next afterwards.

Thanks!

Dmitry Osipenko (2):
  dma-buf: Make locking consistent in dma_buf_detach()
  drm/gem: Check whether object is NULL in drm_gem_vunmap()

 drivers/dma-buf/dma-buf.c | 3 ++-
 drivers/gpu/drm/drm_gem.c | 9 ++---
 2 files changed, 8 insertions(+), 4 deletions(-)

-- 
2.37.3



Re: [PATCH v6 22/23] drm/vc4: vec: Add support for more analog TV standards

2022-10-26 Thread Mateusz Kwiatkowski
Hi Maxime,

I've seen that you've incorporated my PAL60 patch. Thanks!

I still yet need to test your v6 changes, but looking at this code with just my
mental static analysis, it seems to me that the vc4_vec_encoder_atomic_check()
should have the tv_mode validation. I should've added it to the PAL60 patch,
but it somehow slipped my mind then.

Anyway, I mentioned it previously here:
https://lore.kernel.org/dri-devel/0f2beec2-ae8e-5579-f0b6-a73d9dae1...@gmail.com/

It would look something like this, inside vc4_vec_encoder_atomic_check():

+   const struct vc4_vec_tv_mode *tv_mode =
+   vc4_vec_tv_mode_lookup(conn_state->tv.mode);
+
+   if (!tv_mode)
+   return -EINVAL;

Without this, it's possible to set e.g. 480i mode and SECAM, which will fail -
but with the current version it will only fail in vc4_vec_encoder_enable(),
which cannot return an error, and in my experience that causes a rather lengthy
lockup.

But, like I said, I still need to actually test that with this version.

Anyway, I was also thinking about adding support for the more "exotic"
non-standard modes. NTSC-50 is, unfortunately, impossible with VEC, but
PAL-N-60 and PAL-M-50 should work. The necessary vc4_vec_tv_modes entries would
look something like:

@@ -325,12 +325,28 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   /* PAL-M-50 */
+   .mode = DRM_MODE_TV_MODE_PAL,
+   .expected_htotal = 864,
+   .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x21e6efe3,
+   },
{
.mode = DRM_MODE_TV_MODE_PAL_N,
.expected_htotal = 864,
.config0 = VEC_CONFIG0_PAL_N_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   /* PAL-N-60 */
+   .mode = DRM_MODE_TV_MODE_PAL_N,
+   .expected_htotal = 858,
+   .config0 = VEC_CONFIG0_PAL_M_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x21f69446,
+   },
{
.mode = DRM_MODE_TV_MODE_SECAM,
.expected_htotal = 864,

I'm not sure if we actually want to add that. The two arguments for doing so
I can think of is 1. it should work, so "why not", 2. it means that more modes
will result in _some_ kind of a valid signal, rather than erroring out, which
is always a plus in my book. I can also think of a hypothetical use case, like
someone in South America with an old PAL-N-only set that would nevertheless
still sync at 60 Hz (perhaps with the help of messing with vertical hold knob),
who would like to play retro games at 60 Hz in color.

But on the other hand, I admit that this scenario is likely a stretch and the
number of people who would actually use it is probably close to the proverbial
two ;) So it's your call, I'm just leaving those settings here just in case.

I'll get back in a couple of days when I do some testing of this v6 patchset.

Best regards,
Mateusz Kwiatkowski

W dniu 26.10.2022 o 17:33, max...@cerno.tech pisze:
> 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.
>
> Acked-by: Noralf Trønnes 
> Signed-off-by: Mateusz Kwiatkowski 
> Signed-off-by: Maxime Ripard 
>
> ---
> Changes in v6:
> - Support PAL60 again
> ---
>  drivers/gpu/drm/vc4/vc4_vec.c | 111 
> --
>  1 file changed, 107 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index 1dda451c8def..d82aef168075 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 

Re: [PATCH v6 16/23] drm/probe-helper: Provide a TV get_modes helper

2022-10-26 Thread Mateusz Kwiatkowski
Hi Maxime,

First of all, nice idea with the helper function that can be reused by different
drivers. This is neat!

But looking at this function, it feels a bit overcomplicated. You're creating
the two modes, then checking which one is the default, then set the preferred
one and possibly reorder them. Maybe it can be simplified somehow?

Although when I tried to refactor it myself, I ended up with something that's
not better at all. Maybe it needs to be complicated, after all :(

Anyway, the current version seems to have a couple of bugs:

> + if (tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL_N) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_SECAM)) {
> + mode = drm_mode_analog_pal_576i(connector->dev);
> + if (!mode)
> + return 0;
> +
> + tv_modes[count++] = mode;
> + }

If the 480i mode has been created properly, but there's an error creating the
576i one (we enter the if (!mode) clause), the 480i mode will leak.

> + if (count == 1) {

You're handling the count == 1 case specially, but if count == 0, the rest of
the code will assume that two modes exist and probably segfault in the process.

> + ret = drm_object_property_get_default_value(>base,
> + 
> dev->mode_config.tv_mode_property,
> + _mode);
> + if (ret)
> + return 0;
> +
> + if (cmdline->tv_mode_specified)
> + default_mode = cmdline->tv_mode;

In case of an error (ret != 0), the modes created so far in the tv_modes array
will leak.

Also, I wonder if maybe the if (cmdline->tv_mode_specified) clause should go
first? If we're going to use the default from cmdline, there's no point in even
querying the property default value.

Best regards,
Mateusz Kwiatkowski



Re: [PATCH] drm/tests: Add back seed value information

2022-10-26 Thread André Almeida

Hi Grillo :)

On 10/26/22 18:14, Arthur Grillo wrote:

As reported by Michał the drm_mm and drm_buddy unit tests lost the
printk with seed value after they being refactored into kunit. This
patch adds back this important information to assure reproducibility
converting them to use the kunit api.



You should write you commit message in imperative form, like "Add back 
this important [...]"



Signed-off-by: Arthur Grillo 
Reported-by: Michał Winiarski 
---
  drivers/gpu/drm/tests/drm_buddy_test.c | 3 +++
  drivers/gpu/drm/tests/drm_mm_test.c| 4 +++-
  2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c 
b/drivers/gpu/drm/tests/drm_buddy_test.c
index 62f69589a72d..83c8863bc643 100644
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ b/drivers/gpu/drm/tests/drm_buddy_test.c
@@ -731,6 +731,9 @@ static int drm_buddy_init_test(struct kunit *test)
while (!random_seed)
random_seed = get_random_u32();
  
+	kunit_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",


DRM buddy manager (struct drm_buddy)

seems a bit redundant to me.


+   random_seed);
+
return 0;
  }
  
diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c

index c4b66eeae203..492347069d58 100644
--- a/drivers/gpu/drm/tests/drm_mm_test.c
+++ b/drivers/gpu/drm/tests/drm_mm_test.c
@@ -2214,6 +2214,9 @@ static int drm_mm_init_test(struct kunit *test)
while (!random_seed)
random_seed = get_random_u32();
  
+	kunit_info("Testing DRM range manager (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n",

+   random_seed, max_iterations, max_prime);
+
return 0;
  }
  
@@ -2251,6 +2254,5 @@ static struct kunit_suite drm_mm_test_suite = {

  };
  
  kunit_test_suite(drm_mm_test_suite);

-
  MODULE_AUTHOR("Intel Corporation");
  MODULE_LICENSE("GPL");


Re: [PATCH] drm/tests: Add back seed value information

2022-10-26 Thread Maíra Canal
Hi Arthur,

On 10/26/22 18:14, Arthur Grillo wrote:
> As reported by Michał the drm_mm and drm_buddy unit tests lost the
> printk with seed value after they being refactored into kunit. This

Some grammar nits:
- s/being/were
- s/kunit/KUnit

> patch adds back this important information to assure reproducibility
> converting them to use the kunit api.
> 
> Signed-off-by: Arthur Grillo 
> Reported-by: Michał Winiarski 

I believe that Michał's should come before your tag, as the SoB chain
should reflect the real route a patch took as it was propagated to the
maintainers [1].

> ---
>  drivers/gpu/drm/tests/drm_buddy_test.c | 3 +++
>  drivers/gpu/drm/tests/drm_mm_test.c| 4 +++-
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c 
> b/drivers/gpu/drm/tests/drm_buddy_test.c
> index 62f69589a72d..83c8863bc643 100644
> --- a/drivers/gpu/drm/tests/drm_buddy_test.c
> +++ b/drivers/gpu/drm/tests/drm_buddy_test.c
> @@ -731,6 +731,9 @@ static int drm_buddy_init_test(struct kunit *test)
>   while (!random_seed)
>   random_seed = get_random_u32();
>  
> + kunit_info("Testing DRM buddy manager (struct drm_buddy), with 
> random_seed=0x%x\n",
> + random_seed);

I'm getting some compiling errors here:

ERROR:root:../drivers/gpu/drm/tests/drm_buddy_test.c:735:3: error:
expected ')'
random_seed);
^
../drivers/gpu/drm/tests/drm_buddy_test.c:734:2: note: to match this '('
kunit_info("Testing DRM buddy manager (struct drm_buddy), with
random_seed=0x%x\n",
^

You can reproduce it by running:

$ ./tools/testing/kunit/kunit.py --kunitconfig=drivers/gpu/drm/tests

Moreover, could you address the checkpatch issues? There are some
misaligned parenthesis and the line are too big.

> +
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/tests/drm_mm_test.c 
> b/drivers/gpu/drm/tests/drm_mm_test.c
> index c4b66eeae203..492347069d58 100644
> --- a/drivers/gpu/drm/tests/drm_mm_test.c
> +++ b/drivers/gpu/drm/tests/drm_mm_test.c
> @@ -2214,6 +2214,9 @@ static int drm_mm_init_test(struct kunit *test)
>   while (!random_seed)
>   random_seed = get_random_u32();
>  
> + kunit_info("Testing DRM range manager (struct drm_mm), with 
> random_seed=0x%x max_iterations=%u max_prime=%u\n",
> + random_seed, max_iterations, max_prime);
> +

Same here.

>   return 0;
>  }
>  
> @@ -2251,6 +2254,5 @@ static struct kunit_suite drm_mm_test_suite = {
>  };
>  
>  kunit_test_suite(drm_mm_test_suite);
> -

There is no need to change this line.

Thanks for your patch!

[1]
https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin

Best Regards,
- Maíra Canal


>  MODULE_AUTHOR("Intel Corporation");
>  MODULE_LICENSE("GPL");


Re: [PATCH 10/10] iommufd: Allow iommufd to supply /dev/vfio/vfio

2022-10-26 Thread Alex Williamson
On Tue, 25 Oct 2022 15:50:45 -0300
Jason Gunthorpe  wrote:

> If the VFIO container is compiled out, give a kconfig option for iommufd
> to provide the miscdev node with the same name and permissions as vfio
> uses.
> 
> The compatibility node supports the same ioctls as VFIO and automatically
> enables the VFIO compatible pinned page accounting mode.

I think I'd like to see some sort of breadcrumb when /dev/vfio/vfio is
provided by something other than the vfio container code.  If we intend
to include this before P2P is resolved, that breadcrumb (dmesg I'm
guessing) might also list any known limitations of the compatibility to
save time with debugging.  Thanks,

Alex

> Signed-off-by: Jason Gunthorpe 
> ---
>  drivers/iommu/iommufd/Kconfig | 12 
>  drivers/iommu/iommufd/main.c  | 35 ---
>  2 files changed, 44 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/iommufd/Kconfig b/drivers/iommu/iommufd/Kconfig
> index f0a2012234fa09..afc83b7575cce6 100644
> --- a/drivers/iommu/iommufd/Kconfig
> +++ b/drivers/iommu/iommufd/Kconfig
> @@ -14,6 +14,18 @@ config IOMMUFD
> If you don't know what to do here, say N.
>  
>  if IOMMUFD
> +config IOMMUFD_VFIO_CONTAINER
> + bool "IOMMUFD provides the VFIO container /dev/vfio/vfio"
> + depends on VFIO && !VFIO_CONTAINER
> + default VFIO && !VFIO_CONTAINER
> + help
> +   IOMMUFD will provide /dev/vfio/vfio instead of VFIO. This relies on
> +   IOMMUFD providing compatibility emulation to give the same ioctls.
> +   It provides an option to build a kernel with legacy VFIO components
> +   removed.
> +
> +   Unless testing IOMMUFD say N here.
> +
>  config IOMMUFD_TEST
>   bool "IOMMU Userspace API Test support"
>   depends on RUNTIME_TESTING_MENU
> diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
> index 8a31c1a14cdd53..19db81fbf7f08f 100644
> --- a/drivers/iommu/iommufd/main.c
> +++ b/drivers/iommu/iommufd/main.c
> @@ -24,6 +24,7 @@
>  #include 
>  #include 
>  
> +#include "io_pagetable.h"
>  #include "iommufd_private.h"
>  #include "iommufd_test.h"
>  
> @@ -31,6 +32,7 @@ struct iommufd_object_ops {
>   void (*destroy)(struct iommufd_object *obj);
>  };
>  static struct iommufd_object_ops iommufd_object_ops[];
> +static struct miscdevice vfio_misc_dev;
>  
>  struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
>size_t size,
> @@ -167,6 +169,13 @@ static int iommufd_fops_open(struct inode *inode, struct 
> file *filp)
>   if (!ictx)
>   return -ENOMEM;
>  
> + /*
> +  * For compatibility with VFIO when /dev/vfio/vfio is opened we default
> +  * to the same rlimit accounting as vfio uses.
> +  */
> + if (filp->private_data == _misc_dev)
> + ictx->account_mode = IOPT_PAGES_ACCOUNT_MM;
> +
>   xa_init_flags(>objects, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
>   ictx->file = filp;
>   filp->private_data = ictx;
> @@ -392,26 +401,46 @@ static struct miscdevice iommu_misc_dev = {
>   .mode = 0660,
>  };
>  
> +
> +static struct miscdevice vfio_misc_dev = {
> + .minor = VFIO_MINOR,
> + .name = "vfio",
> + .fops = _fops,
> + .nodename = "vfio/vfio",
> + .mode = 0666,
> +};
> +
>  static int __init iommufd_init(void)
>  {
>   int ret;
>  
>   ret = misc_register(_misc_dev);
> - if (ret) {
> - pr_err("Failed to register misc device\n");
> + if (ret)
>   return ret;
> - }
>  
> + if (IS_ENABLED(CONFIG_IOMMUFD_VFIO_CONTAINER)) {
> + ret = misc_register(_misc_dev);
> + if (ret)
> + goto err_misc;
> + }
>   return 0;
> +err_misc:
> + misc_deregister(_misc_dev);
> + return ret;
>  }
>  
>  static void __exit iommufd_exit(void)
>  {
> + if (IS_ENABLED(CONFIG_IOMMUFD_VFIO_CONTAINER))
> + misc_deregister(_misc_dev);
>   misc_deregister(_misc_dev);
>  }
>  
>  module_init(iommufd_init);
>  module_exit(iommufd_exit);
>  
> +#if IS_ENABLED(CONFIG_IOMMUFD_VFIO_CONTAINER)
> +MODULE_ALIAS_MISCDEV(VFIO_MINOR);
> +#endif
>  MODULE_DESCRIPTION("I/O Address Space Management for passthrough devices");
>  MODULE_LICENSE("GPL");



Re: [PATCH v6 14/23] drm/modes: Properly generate a drm_display_mode from a named mode

2022-10-26 Thread Mateusz Kwiatkowski

Hi Maxime,


+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 = _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;
+}
+


You didn't add tv_mode_specified to struct drm_named_mode, and left the
if (!named_mode->tv_mode) condition here. This will break on NTSC.

Best regards,
Mateusz Kwiatkowski



Re: [PATCH 04/10] vfio: Move storage of allow_unsafe_interrupts to vfio_main.c

2022-10-26 Thread Alex Williamson
On Tue, 25 Oct 2022 15:17:10 -0300
Jason Gunthorpe  wrote:

> This legacy module knob has become uAPI, when set on the vfio_iommu_type1
> it disables some security protections in the iommu drivers. Move the
> storage for this knob to vfio_main.c so that iommufd can access it too.

I don't really understand this, we're changing the behavior of the
iommufd_device_attach() operation based on the modules options of
vfio_iommu_type1, which may not be loaded or even compiled into the
kernel.  Our compatibility story falls apart when VFIO_CONTAINER is not
set, iommufd sneaks in to usurp /dev/vfio/vfio, and the user's module
options for type1 go unprocessed.

I hate to suggest that type1 becomes a module that does nothing more
than maintain consistency of this variable when the full type1 isn't
available, but is that what we need to do?  Thanks,

Alex

> Signed-off-by: Jason Gunthorpe 
> ---
>  drivers/vfio/vfio.h | 2 ++
>  drivers/vfio/vfio_iommu_type1.c | 5 ++---
>  drivers/vfio/vfio_main.c| 3 +++
>  3 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
> index f95f4925b83bbd..54e5a8e0834ccb 100644
> --- a/drivers/vfio/vfio.h
> +++ b/drivers/vfio/vfio.h
> @@ -130,4 +130,6 @@ extern bool vfio_noiommu __read_mostly;
>  enum { vfio_noiommu = false };
>  #endif
>  
> +extern bool vfio_allow_unsafe_interrupts;
> +
>  #endif
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 23c24fe98c00d4..186e33a006d314 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -44,9 +44,8 @@
>  #define DRIVER_AUTHOR   "Alex Williamson "
>  #define DRIVER_DESC "Type1 IOMMU driver for VFIO"
>  
> -static bool allow_unsafe_interrupts;
>  module_param_named(allow_unsafe_interrupts,
> -allow_unsafe_interrupts, bool, S_IRUGO | S_IWUSR);
> +vfio_allow_unsafe_interrupts, bool, S_IRUGO | S_IWUSR);
>  MODULE_PARM_DESC(allow_unsafe_interrupts,
>"Enable VFIO IOMMU support for on platforms without interrupt 
> remapping support.");
>  
> @@ -2282,7 +2281,7 @@ static int vfio_iommu_type1_attach_group(void 
> *iommu_data,
>   iommu_group_for_each_dev(iommu_group, (void 
> *)IOMMU_CAP_INTR_REMAP,
>vfio_iommu_device_capable);
>  
> - if (!allow_unsafe_interrupts && !msi_remap) {
> + if (!vfio_allow_unsafe_interrupts && !msi_remap) {
>   pr_warn("%s: No interrupt remapping support.  Use the module 
> param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this 
> platform\n",
>  __func__);
>   ret = -EPERM;
> diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
> index 8d809ecd982b39..1e414b2c48a511 100644
> --- a/drivers/vfio/vfio_main.c
> +++ b/drivers/vfio/vfio_main.c
> @@ -51,6 +51,9 @@ static struct vfio {
>   struct ida  device_ida;
>  } vfio;
>  
> +bool vfio_allow_unsafe_interrupts;
> +EXPORT_SYMBOL_GPL(vfio_allow_unsafe_interrupts);
> +
>  static DEFINE_XARRAY(vfio_device_set_xa);
>  static const struct file_operations vfio_group_fops;
>  



[PATCH] drm: lcdif: Set and enable FIFO Panic threshold

2022-10-26 Thread Marek Vasut
In case the LCDIFv3 is used to drive a 4k panel via i.MX8MP HDMI bridge,
the LCDIFv3 becomes susceptible to FIFO underflows, which lead to nasty
flicker of the image on the panel, or image being shifted by half frame
horizontally every second frame. The flicker can be easily triggered by
running 3D application on top of weston compositor, like neverball or
chromium. Surprisingly glmark2-es2-wayland or glmark2-es2-drm does not
trigger this effect so easily.

Configure the FIFO Panic threshold register and enable the FIFO Panic
mode, which internally boosts the NoC interconnect priority for LCDIFv3
transactions in case of possible underflow. This mitigates the flicker
effect on 4k panels as well.

Fixes: 9db35bb349a0 ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
Signed-off-by: Marek Vasut 
---
Cc: Kieran Bingham 
Cc: Laurent Pinchart 
Cc: Liu Ying 
Cc: Lucas Stach 
Cc: Marco Felsch 
Cc: Martyn Welch 
Cc: Peng Fan 
Cc: Sam Ravnborg 
---
 drivers/gpu/drm/mxsfb/lcdif_kms.c  | 15 +++
 drivers/gpu/drm/mxsfb/lcdif_regs.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index a5302006c02cd..aee7babb5fa5c 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -341,6 +341,18 @@ static void lcdif_enable_controller(struct 
lcdif_drm_private *lcdif)
reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
reg |= CTRLDESCL0_5_EN;
writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
+
+   /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
+   writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_RANGE / 3) |
+  FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_RANGE / 3),
+  lcdif->base + LCDC_V8_PANIC0_THRES);
+
+   /*
+* Enable FIFO Panic, this does not generate interrupt, but
+* boosts NoC priority based on FIFO Panic watermarks.
+*/
+   writel(INT_ENABLE_D1_PLANE_PANIC_EN,
+  lcdif->base + LCDC_V8_INT_ENABLE_D1);
 }
 
 static void lcdif_disable_controller(struct lcdif_drm_private *lcdif)
@@ -348,6 +360,9 @@ static void lcdif_disable_controller(struct 
lcdif_drm_private *lcdif)
u32 reg;
int ret;
 
+   /* Disable FIFO Panic NoC priority booster. */
+   writel(0, lcdif->base + LCDC_V8_INT_ENABLE_D1);
+
reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
reg &= ~CTRLDESCL0_5_EN;
writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
diff --git a/drivers/gpu/drm/mxsfb/lcdif_regs.h 
b/drivers/gpu/drm/mxsfb/lcdif_regs.h
index fb74eb5ccbf1d..3d2f81d6f995e 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_regs.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_regs.h
@@ -255,6 +255,7 @@
 
 #define PANIC0_THRES_LOW_MASK  GENMASK(24, 16)
 #define PANIC0_THRES_HIGH_MASK GENMASK(8, 0)
+#define PANIC0_THRES_RANGE 512
 
 #define LCDIF_MIN_XRES 120
 #define LCDIF_MIN_YRES 120
-- 
2.35.1



Re: [PATCH] drm: lcdif: change burst size to 256B

2022-10-26 Thread Marek Vasut

On 7/26/22 11:43, Marco Felsch wrote:

FIFO underruns are seen if a AXI bus master with a higher priority do a
lot of memory access. Increase the burst size to 256B to avoid such
underruns and to improve the memory access efficiency.

Signed-off-by: Marco Felsch 


Uh, this fell through the cracks, sorry.

Can you please collect my RB, add:

Fixes: 9db35bb349a0 ("drm: lcdif: Add support for i.MX8MP LCDIF variant")

and send V2 ?

btw. the Panic mode seems to work on this IP with 4k displays and HDMI.


Re: [PATCH v5 02/31] drm/i915: Don't register backlight when another backlight should be used (v2)

2022-10-26 Thread Matthew Garrett
On Wed, Oct 26, 2022 at 11:59:28AM +0200, Hans de Goede wrote:

> Ok, so this is a local customization to what is already a custom BIOS
> for a custom motherboard. There is a lot of custom in that sentence and
> TBH at some point things might become too custom for them to be expected
> to work OOTB.

But it *did* work OOTB before. You broke it. I accept that I'm a 
ludicrously weird corner case here, but there are going to be other 
systems that are also affected by this.

> I'm afraid things are not that simple. I assume that with
> "if ACPI backlight control is expected to work" you mean don't
> use ACPI backlight control when (acpi_osi_is_win8() && native_available)
> evaluates to true because it is known to be broken on some of
> those systems because Windows 8 stopped using it ?

Correct.

> Unfortunately something similar applies to vendor interfaces,
> When Windows XP started using (and mandating for certification
> IIRC) ACPI backlight control, vendors still kept their own
> vendor specific EC/smbios/ACPI/WMI backlight interfaces around for
> a long long time, except they were often no longer tested.

The current situation (both before your patchset and with its current 
implementation) is that vendor is preferred to native, so if the vendor 
interface is present then we're already using it.

> > The 
> > problem you're dealing with is that the knowledge of whether or not 
> > there's a vendor interface isn't something the core kernel code knows 
> > about. What you're proposing here is effectively for us to expose 
> > additional information about whether or not there's a vendor interface 
> > in the system firmware, but since we're talking in some cases about 
> > hardware that's almost 20 years old, we're not realistically going to 
> > get those old machines fixed.
> 
> I don't understand why you keep talking about the old vendor interfaces,
> at least for the chromebook part of this thread the issue is that
> the i915 driver no longer registers the intel_backlight device which
> is a native device type, which is caused by the patch this email
> thread is about (and old vendor interfaces do not come into play
> at all here). So AFAICT this is a native vs acpi backlight control
> issue ?

I'm referring to your proposed patch that changed the default from 
backlight_vendor to backlight_native, which would fix my machine and 
Chromebooks but break anything that relies on the vendor interfaces.

> I really want to resolve your bug, but I still lack a lot of info,
> like what backlight interface you were actually using in 6.0 ?

Native.

> {
>  .callback = video_detect_force_video,
>  /* ThinkPad X201s */
>  .matches = {
> DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
> },
> },
> 
> will trigger.

In this case you'd break anyone else running the system who isn't using 
the hacked EC and different ACPI tables - obviously there's ways round 
this, but realistically since I'm (as far as I know) the only person in 
this situation it makes more sense for me to add a kernel parameter than 
carry around an exceedingly niche DMI quirk. I'm fine with that. But the 
point I'm trying to make is that the machines *are* telling you whether 
they'd prefer vendor or native, and you're not taking that into account 
in the video_detect code.


Re: [PATCH -next] drm/amdkfd: Fix NULL pointer dereference in svm_migrate_to_ram()

2022-10-26 Thread Felix Kuehling

On 2022-10-25 22:00, Yang Li wrote:

./drivers/gpu/drm/amd/amdkfd/kfd_migrate.c:985:58-62: ERROR: p is NULL but 
dereferenced.

Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2549
Reported-by: Abaci Robot 
Signed-off-by: Yang Li 


The patch is

Reviewed-by: Felix Kuehling 

I applied to our amd-staging-drm-next branch.

Thanks,
  Felix



---

change in v2:
According to Felix's suggestion, move the pr_debug up before the 
kfd_unref_process
call.

  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 4 +---
  1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 20d6b2578927..b9c8d29d95aa 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -978,12 +978,10 @@ static vm_fault_t svm_migrate_to_ram(struct vm_fault *vmf)
  out_unlock_svms:
mutex_unlock(>svms.lock);
  out_unref_process:
+   pr_debug("CPU fault svms 0x%p address 0x%lx done\n", >svms, addr);
kfd_unref_process(p);
  out_mmput:
mmput(mm);
-
-   pr_debug("CPU fault svms 0x%p address 0x%lx done\n", >svms, addr);
-
return r ? VM_FAULT_SIGBUS : 0;
  }
  


Re: [PATCH v4 06/10] drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()

2022-10-26 Thread Dmitry Baryshkov

On 26/10/2022 21:28, Marijn Suijten wrote:

As per the FIXME this code is entirely duplicate with what is already
provided inside drm_dsc_compute_rc_parameters(), supposedly because that
function was yielding "incorrect" results while in reality the panel
driver(s?) used for testing were providing incorrect parameters.

For example, this code from downstream assumed dsc->bits_per_pixel to
contain an integer value, whereas the upstream drm_dsc_config struct
stores it with 4 fractional bits.  drm_dsc_compute_rc_parameters()
already accounts for this feat while the panel driver used for testing
[1] wasn't, hence making drm_dsc_compute_rc_parameters() seem like it
was returning an incorrect result.
Other users of dsc->bits_per_pixel inside dsi_populate_dsc_params() also
treat it in the same erroneous way, and will be addressed in a separate
patch.
In the end, using drm_dsc_compute_rc_parameters() spares both a lot of
duplicate code and erratic behaviour.

[1]: 
https://git.linaro.org/people/vinod.koul/kernel.git/commit/?h=topic/pixel3_5.18-rc1=1d7d98ad564f1ec69e7525e07418918d90f247a1

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Signed-off-by: Marijn Suijten 
---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 64 +++---
  1 file changed, 6 insertions(+), 58 deletions(-)


Reviewed-by: Dmitry Baryshkov 

Thank you for the expanded explanation.

--
With best wishes
Dmitry



Re: [PATCH v5 09/19] drm/i915/vm_bind: Add out fence support

2022-10-26 Thread Niranjana Vishwanathapura

On Wed, Oct 26, 2022 at 06:15:09PM +0100, Matthew Auld wrote:

On 25/10/2022 07:58, Niranjana Vishwanathapura wrote:

Add support for handling out fence for vm_bind call.

v2: Reset vma->vm_bind_fence.syncobj to NULL at the end
of vm_bind call.
v3: Remove vm_unbind out fence uapi which is not supported yet.
v4: Return error if I915_TIMELINE_FENCE_WAIT fence flag is set.
Wait for bind to complete iff I915_TIMELINE_FENCE_SIGNAL is
not specified.

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Andi Shyti 
---
 drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h   |  4 +
 .../drm/i915/gem/i915_gem_vm_bind_object.c| 93 +++
 drivers/gpu/drm/i915/i915_vma.c   |  7 +-
 drivers/gpu/drm/i915/i915_vma_types.h |  7 ++
 include/uapi/drm/i915_drm.h   | 49 +-
 5 files changed, 157 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h 
b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
index 36262a6357b5..b70e900e35ab 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
@@ -8,6 +8,7 @@
 #include 
+struct dma_fence;
 struct drm_device;
 struct drm_file;
 struct i915_address_space;
@@ -23,4 +24,7 @@ int i915_gem_vm_unbind_ioctl(struct drm_device *dev, void 
*data,
 void i915_gem_vm_unbind_all(struct i915_address_space *vm);
+void i915_vm_bind_signal_fence(struct i915_vma *vma,
+  struct dma_fence * const fence);
+
 #endif /* __I915_GEM_VM_BIND_H */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c 
b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
index 863bd17c9253..fca6d6eb9ef8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
@@ -7,6 +7,8 @@
 #include 
+#include 
+
 #include "gem/i915_gem_context.h"
 #include "gem/i915_gem_vm_bind.h"
@@ -100,6 +102,76 @@ static void i915_gem_vm_bind_remove(struct i915_vma *vma, 
bool release_obj)
i915_gem_object_put(vma->obj);
 }
+static int i915_vm_bind_add_fence(struct drm_file *file, struct i915_vma *vma,
+ u32 handle, u64 point)
+{
+   struct drm_syncobj *syncobj;
+
+   syncobj = drm_syncobj_find(file, handle);
+   if (!syncobj) {
+   DRM_DEBUG("Invalid syncobj handle provided\n");


AFAIK drm_dbg() is preferred, if possible.


ok, will fix.




+   return -ENOENT;
+   }
+
+   /*
+* For timeline syncobjs we need to preallocate chains for
+* later signaling.
+*/
+   if (point) {
+   vma->vm_bind_fence.chain_fence = dma_fence_chain_alloc();
+   if (!vma->vm_bind_fence.chain_fence) {
+   drm_syncobj_put(syncobj);
+   return -ENOMEM;
+   }
+   } else {
+   vma->vm_bind_fence.chain_fence = NULL;
+   }
+   vma->vm_bind_fence.syncobj = syncobj;
+   vma->vm_bind_fence.value = point;
+
+   return 0;
+}
+
+static void i915_vm_bind_put_fence(struct i915_vma *vma)
+{
+   if (!vma->vm_bind_fence.syncobj)
+   return;
+
+   drm_syncobj_put(vma->vm_bind_fence.syncobj);
+   dma_fence_chain_free(vma->vm_bind_fence.chain_fence);
+   vma->vm_bind_fence.syncobj = NULL;
+}
+
+/**
+ * i915_vm_bind_signal_fence() - Add fence to vm_bind syncobj
+ * @vma: vma mapping requiring signaling
+ * @fence: fence to be added
+ *
+ * Associate specified @fence with the @vma's syncobj to be
+ * signaled after the @fence work completes.
+ */
+void i915_vm_bind_signal_fence(struct i915_vma *vma,
+  struct dma_fence * const fence)
+{
+   struct drm_syncobj *syncobj = vma->vm_bind_fence.syncobj;
+
+   if (!syncobj)
+   return;
+
+   if (vma->vm_bind_fence.chain_fence) {
+   drm_syncobj_add_point(syncobj,
+ vma->vm_bind_fence.chain_fence,
+ fence, vma->vm_bind_fence.value);
+   /*
+* The chain's ownership is transferred to the
+* timeline.
+*/
+   vma->vm_bind_fence.chain_fence = NULL;
+   } else {
+   drm_syncobj_replace_fence(syncobj, fence);
+   }
+}
+
 static int i915_gem_vm_unbind_vma(struct i915_address_space *vm,
  struct drm_i915_gem_vm_unbind *va)
 {
@@ -205,6 +277,10 @@ static int i915_gem_vm_bind_obj(struct i915_address_space 
*vm,
if (!va->length || !IS_ALIGNED(va->start, I915_GTT_PAGE_SIZE))
ret = -EINVAL;
+   /* In fences are not supported */
+   if (va->fence.flags & I915_TIMELINE_FENCE_WAIT)
+   ret = -EINVAL;


I guess also:

if (flags & __I915_TIMELINE_FENCE_UNKNOWN_FLAGS)



ok, will add


Reviewed-by: Matthew Auld 



Thanks,
Niranjana


+
obj = i915_gem_object_lookup(file, 

Re: [syzbot] KASAN: use-after-free Read in task_work_run (2)

2022-10-26 Thread syzbot
syzbot has found a reproducer for the following issue on:

HEAD commit:88619e77b33d net: stmmac: rk3588: Allow multiple gmac cont..
git tree:   bpf
console output: https://syzkaller.appspot.com/x/log.txt?x=1646d6f288
kernel config:  https://syzkaller.appspot.com/x/.config?x=a66c6c673fb555e8
dashboard link: https://syzkaller.appspot.com/bug?extid=9228d6098455bb209ec8
compiler:   gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for 
Debian) 2.35.2
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=12bc425e88
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1126516e88

Downloadable assets:
disk image: 
https://storage.googleapis.com/syzbot-assets/f8435d5c2c21/disk-88619e77.raw.xz
vmlinux: 
https://storage.googleapis.com/syzbot-assets/551d8a013e81/vmlinux-88619e77.xz
kernel image: 
https://storage.googleapis.com/syzbot-assets/7d3f5c29064d/bzImage-88619e77.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+9228d6098455bb209...@syzkaller.appspotmail.com

==
BUG: KASAN: use-after-free in task_work_run+0x1b0/0x270 kernel/task_work.c:178
Read of size 8 at addr 8880752b1c18 by task syz-executor361/3766

CPU: 0 PID: 3766 Comm: syz-executor361 Not tainted 
6.1.0-rc2-syzkaller-00073-g88619e77b33d #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
10/11/2022
Call Trace:
 
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
 print_address_description mm/kasan/report.c:284 [inline]
 print_report+0x15e/0x45d mm/kasan/report.c:395
 kasan_report+0xbb/0x1f0 mm/kasan/report.c:495
 task_work_run+0x1b0/0x270 kernel/task_work.c:178
 exit_task_work include/linux/task_work.h:38 [inline]
 do_exit+0xb35/0x2a20 kernel/exit.c:820
 do_group_exit+0xd0/0x2a0 kernel/exit.c:950
 get_signal+0x21a1/0x2430 kernel/signal.c:2858
 arch_do_signal_or_restart+0x82/0x2300 arch/x86/kernel/signal.c:869
 exit_to_user_mode_loop kernel/entry/common.c:168 [inline]
 exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203
 __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
 syscall_exit_to_user_mode+0x19/0x50 kernel/entry/common.c:296
 do_syscall_64+0x42/0xb0 arch/x86/entry/common.c:86
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fb9f674b089
Code: Unable to access opcode bytes at 0x7fb9f674b05f.
RSP: 002b:7fb9f66fb318 EFLAGS: 0246 ORIG_RAX: 00ca
RAX: 0001 RBX: 7fb9f67da1a8 RCX: 7fb9f674b089
RDX: 000f4240 RSI: 0081 RDI: 7fb9f67da1ac
RBP: 7fb9f67da1a0 R08:  R09: 
R10:  R11: 0246 R12: 00310400
R13: 7fff658570cf R14: 7fb9f66fb400 R15: 00022000
 

Allocated by task 3766:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:45
 kasan_set_track+0x21/0x30 mm/kasan/common.c:52
 __kasan_slab_alloc+0x7e/0x80 mm/kasan/common.c:325
 kasan_slab_alloc include/linux/kasan.h:201 [inline]
 slab_post_alloc_hook mm/slab.h:737 [inline]
 slab_alloc_node mm/slub.c:3398 [inline]
 kmem_cache_alloc_node+0x2fc/0x400 mm/slub.c:3443
 perf_event_alloc.part.0+0x69/0x3bc0 kernel/events/core.c:11625
 perf_event_alloc kernel/events/core.c:12174 [inline]
 __do_sys_perf_event_open+0x4ae/0x32d0 kernel/events/core.c:12272
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Freed by task 0:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:45
 kasan_set_track+0x21/0x30 mm/kasan/common.c:52
 kasan_save_free_info+0x2a/0x40 mm/kasan/generic.c:511
 kasan_slab_free mm/kasan/common.c:236 [inline]
 kasan_slab_free+0x160/0x1c0 mm/kasan/common.c:200
 kasan_slab_free include/linux/kasan.h:177 [inline]
 slab_free_hook mm/slub.c:1724 [inline]
 slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1750
 slab_free mm/slub.c:3661 [inline]
 kmem_cache_free+0xea/0x5b0 mm/slub.c:3683
 rcu_do_batch kernel/rcu/tree.c:2250 [inline]
 rcu_core+0x81f/0x1980 kernel/rcu/tree.c:2510
 __do_softirq+0x1f7/0xad8 kernel/softirq.c:571

Last potentially related work creation:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:45
 __kasan_record_aux_stack+0xbc/0xd0 mm/kasan/generic.c:481
 call_rcu+0x99/0x820 kernel/rcu/tree.c:2798
 put_event kernel/events/core.c:5095 [inline]
 perf_event_release_kernel+0x6f2/0x940 kernel/events/core.c:5210
 perf_release+0x33/0x40 kernel/events/core.c:5220
 __fput+0x27c/0xa90 fs/file_table.c:320
 task_work_run+0x16b/0x270 kernel/task_work.c:179
 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
 exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
 exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
 __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
 syscall_exit_to_user_mode+0x19/0x50 kernel/entry/common.c:296
 do_syscall_64+0x42/0xb0 

[PATCH v4 10/10] drm/msm/dsi: Prevent signed BPG offsets from bleeding into adjacent bits

2022-10-26 Thread Marijn Suijten
The bpg_offset array contains negative BPG offsets which fill the full 8
bits of a char thanks to two's complement: this however results in those
bits bleeding into the next field when the value is packed into DSC PPS
by the drm_dsc_helper function, which only expects range_bpg_offset to
contain 6-bit wide values.  As a consequence random slices appear
corrupted on-screen (tested on a Sony Tama Akatsuki device with sdm845).

Use AND operators to limit these two's complement values to 6 bits,
similar to the AMD and i915 drivers.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 4bd8301d2049..5f1fd3f56877 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1804,7 +1804,11 @@ static int dsi_populate_dsc_params(struct msm_dsi_host 
*msm_host, struct drm_dsc
for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
dsc->rc_range_params[i].range_min_qp = min_qp[i];
dsc->rc_range_params[i].range_max_qp = max_qp[i];
-   dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i];
+   /*
+* Range BPG Offset contains two's-complement signed values 
that fill
+* 8 bits, yet the registers and DCS PPS field are only 6 bits 
wide.
+*/
+   dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i] & 
DSC_RANGE_BPG_OFFSET_MASK;
}
 
dsc->initial_offset = 6144; /* Not bpp 12 */
-- 
2.38.1



[PATCH v4 03/10] drm/msm/dsi: Use DIV_ROUND_UP instead of conditional increment on modulo

2022-10-26 Thread Marijn Suijten
This exact same math is used to compute bytes_in_slice above in
dsi_update_dsc_timing(), also used to fill slice_chunk_size.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 80dd9370a258..d9b3e336896f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1829,9 +1829,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
 * params are calculated
 */
groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
-   dsc->slice_chunk_size = dsc->slice_width * dsc->bits_per_pixel / 8;
-   if ((dsc->slice_width * dsc->bits_per_pixel) % 8)
-   dsc->slice_chunk_size++;
+   dsc->slice_chunk_size = DIV_ROUND_UP(dsc->slice_width * 
dsc->bits_per_pixel, 8);
 
/* rbs-min */
min_rate_buffer_size =  dsc->rc_model_size - dsc->initial_offset +
-- 
2.38.1



[PATCH v4 09/10] drm/msm/dpu1: Account for DSC's bits_per_pixel having 4 fractional bits

2022-10-26 Thread Marijn Suijten
According to the comment this DPU register contains the bits per pixel
as a 6.4 fractional value, conveniently matching the contents of
bits_per_pixel in struct drm_dsc_config which also uses 4 fractional
bits.  However, the downstream source this implementation was
copy-pasted from has its bpp field stored _without_ fractional part.

This makes the entire convoluted math obsolete as it is impossible to
pull those 4 fractional bits out of thin air, by somehow trying to reuse
the lowest 2 bits of a non-fractional bpp (lsb = bpp % 4??).

The rest of the code merely attempts to keep the integer part a multiple
of 4, which is rendered useless thanks to data |= dsc->bits_per_pixel <<
12; already filling up those bits anyway (but not on downstream).

Fixes: c110cfd1753e ("drm/msm/disp/dpu1: Add support for DSC")
Signed-off-by: Marijn Suijten 
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
index d3aa062d5ed9..34244bed4a62 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -45,7 +45,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
  u32 initial_lines)
 {
struct dpu_hw_blk_reg_map *c = _dsc->hw;
-   u32 data, lsb, bpp;
+   u32 data;
u32 slice_last_group_size;
u32 det_thresh_flatness;
bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
@@ -59,14 +59,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
data = (initial_lines << 20);
data |= ((slice_last_group_size - 1) << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
-   data |= dsc->bits_per_pixel << 12;
-   lsb = dsc->bits_per_pixel % 4;
-   bpp = dsc->bits_per_pixel / 4;
-   bpp *= 4;
-   bpp <<= 4;
-   bpp |= lsb;
-
-   data |= bpp << 8;
+   data |= (dsc->bits_per_pixel << 8);
data |= (dsc->block_pred_enable << 7);
data |= (dsc->line_buf_depth << 3);
data |= (dsc->simple_422 << 2);
-- 
2.38.1



[PATCH v4 04/10] drm/msm/dsi: Reuse earlier computed dsc->slice_chunk_size

2022-10-26 Thread Marijn Suijten
dsi_populate_dsc_params() is called prior to dsi_update_dsc_timing() and
already computes a value for slice_chunk_size, whose value doesn't need
to be recomputed and re-set here.

Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index d9b3e336896f..70b93e4b62a7 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -845,7 +845,6 @@ static void dsi_update_dsc_timing(struct msm_dsi_host 
*msm_host, bool is_cmd_mod
u32 reg, reg_ctrl, reg_ctrl2;
u32 slice_per_intf, total_bytes_per_intf;
u32 pkt_per_line;
-   u32 bytes_in_slice;
u32 eol_byte_num;
 
/* first calculate dsc parameters and then program
@@ -860,11 +859,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host 
*msm_host, bool is_cmd_mod
if (slice_per_intf > dsc->slice_count)
dsc->slice_count = 1;
 
-   bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 
8);
-
-   dsc->slice_chunk_size = bytes_in_slice;
-
-   total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+   total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf;
 
eol_byte_num = total_bytes_per_intf % 3;
pkt_per_line = slice_per_intf / dsc->slice_count;
@@ -890,7 +885,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host 
*msm_host, bool is_cmd_mod
reg_ctrl |= reg;
 
reg_ctrl2 &= 
~DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH__MASK;
-   reg_ctrl2 |= 
DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice);
+   reg_ctrl2 |= 
DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(dsc->slice_chunk_size);
 
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, 
reg_ctrl);
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, 
reg_ctrl2);
-- 
2.38.1



[PATCH v4 07/10] drm/msm/dsi: Account for DSC's bits_per_pixel having 4 fractional bits

2022-10-26 Thread Marijn Suijten
drm_dsc_config's bits_per_pixel field holds a fractional value with 4
bits, which all panel drivers should adhere to for
drm_dsc_pps_payload_pack() to generate a valid payload.  All code in the
DSI driver here seems to assume that this field doesn't contain any
fractional bits, hence resulting in the wrong values being computed.
Since none of the calculations leave any room for fractional bits or
seem to indicate any possible area of support, disallow such values
altogether.  calculate_rc_params() in intel_vdsc.c performs an identical
bitshift to get at this integer value.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 0d130bded38d..8da27c740c1c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -34,7 +34,7 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc);
+static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct 
drm_dsc_config *dsc);
 
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
@@ -909,6 +909,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi)
u32 va_end = va_start + mode->vdisplay;
u32 hdisplay = mode->hdisplay;
u32 wc;
+   int ret;
 
DBG("");
 
@@ -944,7 +945,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi)
/* we do the calculations for dsc parameters here so that
 * panel can use these parameters
 */
-   dsi_populate_dsc_params(dsc);
+   ret = dsi_populate_dsc_params(msm_host, dsc);
+   if (ret)
+   return;
 
/* Divide the display by 3 but keep back/font porch and
 * pulse width same
@@ -1770,9 +1773,15 @@ static char bpg_offset[DSC_NUM_BUF_RANGES] = {
2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
 };
 
-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
+static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct 
drm_dsc_config *dsc)
 {
int i;
+   u16 bpp = dsc->bits_per_pixel >> 4;
+
+   if (dsc->bits_per_pixel & 0xf) {
+   DRM_DEV_ERROR(_host->pdev->dev, "DSI does not support 
fractional bits_per_pixel\n");
+   return -EINVAL;
+   }
 
dsc->rc_model_size = 8192;
dsc->first_line_bpg_offset = 12;
@@ -1793,8 +1802,8 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i];
}
 
-   dsc->initial_offset = 6144; /* Not bpp 12 */
-   if (dsc->bits_per_pixel != 8)
+   dsc->initial_offset = 6144; /* Not bpp 12 */
+   if (bpp != 8)
dsc->initial_offset = 2048; /* bpp = 12 */
 
if (dsc->bits_per_component <= 10)
-- 
2.38.1



[PATCH v4 05/10] drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc

2022-10-26 Thread Marijn Suijten
This field is currently unread but will come into effect when duplicated
code below is migrated to call drm_dsc_compute_rc_parameters(), which
uses the bpc-dependent value of the local variable mux_words_size in
much the same way.

The hardcoded constant seems to be a remnant from the `/* bpc 8 */`
comment right above, indicating that this group of field assignments is
applicable to bpc = 8 exclusively and should probably bail out on
different bpc values, until constants for other bpc values are added (or
the current ones are confirmed to be correct across multiple bpc's).

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 70b93e4b62a7..a1c387e9b7f4 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1808,6 +1808,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
if (dsc->bits_per_component == 12)
mux_words_size = 64;
 
+   dsc->mux_word_size = mux_words_size;
dsc->initial_xmit_delay = 512;
dsc->initial_scale_value = 32;
dsc->first_line_bpg_offset = 12;
@@ -1818,7 +1819,6 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->flatness_max_qp = 12;
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
-   dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
 
/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
 * params are calculated
-- 
2.38.1



[PATCH v4 06/10] drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()

2022-10-26 Thread Marijn Suijten
As per the FIXME this code is entirely duplicate with what is already
provided inside drm_dsc_compute_rc_parameters(), supposedly because that
function was yielding "incorrect" results while in reality the panel
driver(s?) used for testing were providing incorrect parameters.

For example, this code from downstream assumed dsc->bits_per_pixel to
contain an integer value, whereas the upstream drm_dsc_config struct
stores it with 4 fractional bits.  drm_dsc_compute_rc_parameters()
already accounts for this feat while the panel driver used for testing
[1] wasn't, hence making drm_dsc_compute_rc_parameters() seem like it
was returning an incorrect result.
Other users of dsc->bits_per_pixel inside dsi_populate_dsc_params() also
treat it in the same erroneous way, and will be addressed in a separate
patch.
In the end, using drm_dsc_compute_rc_parameters() spares both a lot of
duplicate code and erratic behaviour.

[1]: 
https://git.linaro.org/people/vinod.koul/kernel.git/commit/?h=topic/pixel3_5.18-rc1=1d7d98ad564f1ec69e7525e07418918d90f247a1

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 64 +++---
 1 file changed, 6 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index a1c387e9b7f4..0d130bded38d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -21,6 +21,7 @@
 
 #include 
 
+#include 
 #include 
 
 #include "dsi.h"
@@ -1771,14 +1772,6 @@ static char bpg_offset[DSC_NUM_BUF_RANGES] = {
 
 static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
 {
-   int mux_words_size;
-   int groups_per_line, groups_total;
-   int min_rate_buffer_size;
-   int hrd_delay;
-   int pre_num_extra_mux_bits, num_extra_mux_bits;
-   int slice_bits;
-   int data;
-   int final_value, final_scale;
int i;
 
dsc->rc_model_size = 8192;
@@ -1804,11 +1797,11 @@ static int dsi_populate_dsc_params(struct 
drm_dsc_config *dsc)
if (dsc->bits_per_pixel != 8)
dsc->initial_offset = 2048; /* bpp = 12 */
 
-   mux_words_size = 48;/* bpc == 8/10 */
-   if (dsc->bits_per_component == 12)
-   mux_words_size = 64;
+   if (dsc->bits_per_component <= 10)
+   dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+   else
+   dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
 
-   dsc->mux_word_size = mux_words_size;
dsc->initial_xmit_delay = 512;
dsc->initial_scale_value = 32;
dsc->first_line_bpg_offset = 12;
@@ -1820,52 +1813,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
 
-   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
-* params are calculated
-*/
-   groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
-   dsc->slice_chunk_size = DIV_ROUND_UP(dsc->slice_width * 
dsc->bits_per_pixel, 8);
-
-   /* rbs-min */
-   min_rate_buffer_size =  dsc->rc_model_size - dsc->initial_offset +
-   dsc->initial_xmit_delay * dsc->bits_per_pixel +
-   groups_per_line * dsc->first_line_bpg_offset;
-
-   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->bits_per_pixel);
-
-   dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
-
-   dsc->initial_scale_value = 8 * dsc->rc_model_size /
-  (dsc->rc_model_size - 
dsc->initial_offset);
-
-   slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height;
-
-   groups_total = groups_per_line * dsc->slice_height;
-
-   data = dsc->first_line_bpg_offset * 2048;
-
-   dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
-
-   pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * 
dsc->bits_per_component + 4) - 2);
-
-   num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size -
-((slice_bits - pre_num_extra_mux_bits) % 
mux_words_size));
-
-   data = 2048 * (dsc->rc_model_size - dsc->initial_offset + 
num_extra_mux_bits);
-   dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
-
-   data = dsc->initial_xmit_delay * dsc->bits_per_pixel;
-   final_value =  dsc->rc_model_size - data + num_extra_mux_bits;
-   dsc->final_offset = final_value;
-
-   final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - 
final_value);
-
-   data = (final_scale - 9) * (dsc->nfl_bpg_offset + 
dsc->slice_bpg_offset);
-   dsc->scale_increment_interval = (2048 * dsc->final_offset) / data;
-
-   dsc->scale_decrement_interval = groups_per_line / 
(dsc->initial_scale_value - 8);
-
-   return 0;
+   return drm_dsc_compute_rc_parameters(dsc);
 }
 
 static int 

[PATCH v4 08/10] drm/msm/dsi: Disallow 8 BPC DSC configuration for alternative BPC values

2022-10-26 Thread Marijn Suijten
According to the `/* bpc 8 */` comment below only values for a
bits_per_component of 8 are currently hardcoded in place.  This is
further confirmed by downstream sources [1] containing different
constants for other BPC values (and different initial_offset too,
with an extra dependency on bits_per_pixel).  Prevent future mishaps by
explicitly disallowing any other bits_per_component value until the
right parameters are put in place and tested.

[1]: 
https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/DISPLAY.LA.2.0.r1-08000-WAIPIO.0/msm/sde_dsc_helper.c#L110-139

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8da27c740c1c..4bd8301d2049 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1783,6 +1783,11 @@ static int dsi_populate_dsc_params(struct msm_dsi_host 
*msm_host, struct drm_dsc
return -EINVAL;
}
 
+   if (dsc->bits_per_component != 8) {
+   DRM_DEV_ERROR(_host->pdev->dev, "DSI does not support 
bits_per_component != 8 yet\n");
+   return -EOPNOTSUPP;
+   }
+
dsc->rc_model_size = 8192;
dsc->first_line_bpg_offset = 12;
dsc->rc_edge_factor = 6;
-- 
2.38.1



[PATCH v4 01/10] drm/msm/dsi: Remove useless math in DSC calculations

2022-10-26 Thread Marijn Suijten
Multiplying a value by 2 and adding 1 to it always results in a value
that is uneven, and that 1 gets truncated immediately when performing
integer division by 2 again.  There is no "rounding" possible here.

After that target_bpp_x16 is used to store a multiplication of
bits_per_pixel by 16 which is only ever read to immediately be divided
by 16 again, and is elided in much the same way.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e82eef031ed4..d645fcbb0683 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1784,7 +1784,6 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
int hrd_delay;
int pre_num_extra_mux_bits, num_extra_mux_bits;
int slice_bits;
-   int target_bpp_x16;
int data;
int final_value, final_scale;
int i;
@@ -1864,14 +1863,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
data = 2048 * (dsc->rc_model_size - dsc->initial_offset + 
num_extra_mux_bits);
dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
 
-   /* bpp * 16 + 0.5 */
-   data = dsc->bits_per_pixel * 16;
-   data *= 2;
-   data++;
-   data /= 2;
-   target_bpp_x16 = data;
-
-   data = (dsc->initial_xmit_delay * target_bpp_x16) / 16;
+   data = dsc->initial_xmit_delay * dsc->bits_per_pixel;
final_value =  dsc->rc_model_size - data + num_extra_mux_bits;
dsc->final_offset = final_value;
 
-- 
2.38.1



[PATCH v4 02/10] drm/msm/dsi: Remove repeated calculation of slice_per_intf

2022-10-26 Thread Marijn Suijten
slice_per_intf is already computed for intf_width, which holds the same
value as hdisplay.

Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration")
Reviewed-by: Bjorn Andersson 
Reviewed-by: Konrad Dybcio 
Reviewed-by: Abhinav Kumar 
Reviewed-by: Vinod Koul 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Marijn Suijten 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index d645fcbb0683..80dd9370a258 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -842,7 +842,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, 
bool enable,
 static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool 
is_cmd_mode, u32 hdisplay)
 {
struct drm_dsc_config *dsc = msm_host->dsc;
-   u32 reg, intf_width, reg_ctrl, reg_ctrl2;
+   u32 reg, reg_ctrl, reg_ctrl2;
u32 slice_per_intf, total_bytes_per_intf;
u32 pkt_per_line;
u32 bytes_in_slice;
@@ -851,8 +851,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host 
*msm_host, bool is_cmd_mod
/* first calculate dsc parameters and then program
 * compress mode registers
 */
-   intf_width = hdisplay;
-   slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width);
+   slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
 
/* If slice_per_pkt is greater than slice_per_intf
 * then default to 1. This can happen during partial
@@ -861,7 +860,6 @@ static void dsi_update_dsc_timing(struct msm_dsi_host 
*msm_host, bool is_cmd_mod
if (slice_per_intf > dsc->slice_count)
dsc->slice_count = 1;
 
-   slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 
8);
 
dsc->slice_chunk_size = bytes_in_slice;
-- 
2.38.1



[PATCH v4 00/10] drm/msm: Fix math issues in MSM DSC implementation

2022-10-26 Thread Marijn Suijten
Various removals of complex yet unnecessary math, fixing all uses of
drm_dsc_config::bits_per_pixel to deal with the fact that this field
includes four fractional bits, and finally making sure that
range_bpg_offset contains values 6-bits wide to prevent overflows in
drm_dsc_pps_payload_pack().

Altogether this series is responsible for solving _all_ Display Stream
Compression issues and artifacts on the Sony Tama (sdm845) Akatsuki
smartphone (2880x1440p).

Changes since v3:
- Swap patch 7 and 8 to make sure msm_host is available inside
  dsi_populate_dsc_params();
- Reword patch 6 (Migrate to drm_dsc_compute_rc_parameters()) to more
  clearly explain why the FIXME wasn't solved initially, but why it can
  (and should!) be resolved now.

v3: 
https://lore.kernel.org/linux-arm-msm/20221009184824.457416-1-marijn.suij...@somainline.org/T/#u

Changes since v2:
- Generalize mux_word_size setting depending on bits_per_component;
- Migrate DSI's DSC calculations to drm_dsc_compute_rc_parameters(),
  implicitly addressing existing math issues;
- Disallow any bits_per_component other than 8, until hardcoded values
  are updated and tested to support such cases.

v2: 
https://lore.kernel.org/linux-arm-msm/20221005181657.784375-1-marijn.suij...@somainline.org/T/#u

Changes since v1:

- Propagate r-b's, except (obviously) in patches that were (heavily)
  modified;
- Remove accidental debug code in dsi_cmd_dma_add;
- Move Range BPG Offset masking out of DCS PPS packing, back into the
  DSI driver when it is assigned to drm_dsc_config (this series is now
  strictly focusing on drm/msm again);
- Replace modulo-check resulting in conditional increment with
  DIV_ROUND_UP;
- Remove repeated calculation of slice_chunk_size;
- Use u16 instead of int when handling bits_per_pixel;
- Use DRM_DEV_ERROR instead of pr_err in DSI code;
- Also remove redundant target_bpp_x16 variable.

v1: 
https://lore.kernel.org/linux-arm-msm/20221001190807.358691-1-marijn.suij...@somainline.org/T/#u

Marijn Suijten (10):
  drm/msm/dsi: Remove useless math in DSC calculations
  drm/msm/dsi: Remove repeated calculation of slice_per_intf
  drm/msm/dsi: Use DIV_ROUND_UP instead of conditional increment on
modulo
  drm/msm/dsi: Reuse earlier computed dsc->slice_chunk_size
  drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc
  drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()
  drm/msm/dsi: Account for DSC's bits_per_pixel having 4 fractional bits
  drm/msm/dsi: Disallow 8 BPC DSC configuration for alternative BPC
values
  drm/msm/dpu1: Account for DSC's bits_per_pixel having 4 fractional
bits
  drm/msm/dsi: Prevent signed BPG offsets from bleeding into adjacent
bits

 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c |  11 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c | 121 ++---
 2 files changed, 37 insertions(+), 95 deletions(-)

--
2.38.1



RE: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

2022-10-26 Thread Liu, Shaoyun
[AMD Official Use Only - General]

The SRIOV already has its own reset routine amdgpu_device_reset_sriov,  we try 
to put the sriov specific sequence  inside this function. For the rest 
part(re-submitting etc ) we should try to have the same  behavior as bare-metal.
Can  we just don't do the re-submission for all kind of reset since kernel 
already signal the reset event  to user level (at least for compute stack) ?

Regard
Sshaoyun.liu

-Original Message-
From: Koenig, Christian 
Sent: Wednesday, October 26, 2022 1:27 PM
To: Liu, Shaoyun ; Tuikov, Luben ; 
Prosyak, Vitaly ; Deucher, Alexander 
; daniel.vet...@ffwll.ch; 
amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

The problem is that this re-submitting is currently an integral part of how 
SRIOV works.

The host can send a function level reset request to the clients when it sees 
that some schedule switching didn't worked as expected and in this case (and 
only this case) the hardware has actually never started to even work on the 
IBs. So the re-submission is actually save from this side.

But in general you are right, the sw side is just completely broken because we 
came up with a bunch of rather strict rules for the dma_fence implementation 
(and those rules are perfectly valid and necessary).

Regards,
Christian.

Am 26.10.22 um 18:10 schrieb Liu, Shaoyun:
> [AMD Official Use Only - General]
>
> The  user space  shouldn't care about  SRIOV or not ,  I don't think we need 
> to keep the re-submission for SRIOV as well.  The reset from SRIOV could 
> trigger the  host do a whole GPU reset which will have the same issue as bare 
> metal.
>
> Regards
> Shaoyun.liu
>
> -Original Message-
> From: amd-gfx  On Behalf Of
> Christian König
> Sent: Wednesday, October 26, 2022 11:36 AM
> To: Tuikov, Luben ; Prosyak, Vitaly
> ; Deucher, Alexander
> ; daniel.vet...@ffwll.ch;
> amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> Cc: Koenig, Christian 
> Subject: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal
> reset
>
> Re-submitting IBs by the kernel has many problems because pre- requisite 
> state is not automatically re-created as well. In other words neither binary 
> semaphores nor things like ring buffer pointers are in the state they should 
> be when the hardware starts to work on the IBs again.
>
> Additional to that even after more than 5 years of developing this feature it 
> is still not stable and we have massively problems getting the reference 
> counts right.
>
> As discussed with user space developers this behavior is not helpful in the 
> first place. For graphics and multimedia workloads it makes much more sense 
> to either completely re-create the context or at least re-submitting the IBs 
> from userspace.
>
> For compute use cases re-submitting is also not very helpful since userspace 
> must rely on the accuracy of the result.
>
> Because of this we stop this practice and instead just properly note that the 
> fence submission was canceled. The only use case we keep the re-submission 
> for now is SRIOV and function level resets.
>
> Signed-off-by: Christian König 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index d4584e577b51..39e94feba1ac 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -5288,7 +5288,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device 
> *adev,
>  continue;
>
>  /* No point to resubmit jobs if we didn't HW reset*/
> -   if (!tmp_adev->asic_reset_res && !job_signaled)
> +   if (!tmp_adev->asic_reset_res && !job_signaled &&
> +   amdgpu_sriov_vf(tmp_adev))
>
> drm_sched_resubmit_jobs(>sched);
>
>  drm_sched_start(>sched,
> !tmp_adev->asic_reset_res);
> --
> 2.25.1
>



Re: [PATCH v3 01/12] dt-bindings: display/msm: Add binding for SC8280XP MDSS

2022-10-26 Thread Rob Herring
On Tue, Oct 25, 2022 at 08:26:13PM -0700, Bjorn Andersson wrote:
> From: Bjorn Andersson 
> 
> Add binding for the display subsystem and display processing unit in the
> Qualcomm SC8280XP platform.
> 
> Signed-off-by: Bjorn Andersson 
> Signed-off-by: Bjorn Andersson 
> ---
> 
> Changes since v2:
> - Cleaned up description and interconnect definitions
> - Added opp-table
> 
>  .../bindings/display/msm/dpu-sc8280xp.yaml| 287 ++
>  1 file changed, 287 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml

Doesn't this need to be reworked to match Dmitry's restructuring?

> 
> diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml 
> b/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml
> new file mode 100644
> index ..24e7a1562fe7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc8280xp.yaml
> @@ -0,0 +1,287 @@
> +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/msm/dpu-sc8280xp.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Display Processing Unit for SC8280XP
> +
> +maintainers:
> +  - Bjorn Andersson 
> +
> +description:
> +  Device tree bindings for MSM Mobile Display Subsystem (MDSS) that 
> encapsulates
> +  sub-blocks like DPU display controller, DSI and DP interfaces etc.
> +
> +properties:
> +  compatible:
> +const: qcom,sc8280xp-mdss
> +
> +  reg:
> +maxItems: 1
> +
> +  reg-names:
> +const: mdss
> +
> +  power-domains:
> +maxItems: 1
> +
> +  clocks:
> +items:
> +  - description: Display AHB clock from gcc
> +  - description: Display AHB clock from dispcc
> +  - description: Display core clock
> +
> +  clock-names:
> +items:
> +  - const: iface
> +  - const: ahb
> +  - const: core
> +
> +  interrupts:
> +maxItems: 1
> +
> +  interrupt-controller: true
> +

> +  "#address-cells": true
> +
> +  "#size-cells": true

enum: [ 1, 2 ]

(Nothing else sets that)

Rob


Re: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

2022-10-26 Thread Christian König
The problem is that this re-submitting is currently an integral part of 
how SRIOV works.


The host can send a function level reset request to the clients when it 
sees that some schedule switching didn't worked as expected and in this 
case (and only this case) the hardware has actually never started to 
even work on the IBs. So the re-submission is actually save from this side.


But in general you are right, the sw side is just completely broken 
because we came up with a bunch of rather strict rules for the dma_fence 
implementation (and those rules are perfectly valid and necessary).


Regards,
Christian.

Am 26.10.22 um 18:10 schrieb Liu, Shaoyun:

[AMD Official Use Only - General]

The  user space  shouldn't care about  SRIOV or not ,  I don't think we need to 
keep the re-submission for SRIOV as well.  The reset from SRIOV could trigger 
the  host do a whole GPU reset which will have the same issue as bare metal.

Regards
Shaoyun.liu

-Original Message-
From: amd-gfx  On Behalf Of Christian 
König
Sent: Wednesday, October 26, 2022 11:36 AM
To: Tuikov, Luben ; Prosyak, Vitaly ; 
Deucher, Alexander ; daniel.vet...@ffwll.ch; 
amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
Cc: Koenig, Christian 
Subject: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

Re-submitting IBs by the kernel has many problems because pre- requisite state 
is not automatically re-created as well. In other words neither binary 
semaphores nor things like ring buffer pointers are in the state they should be 
when the hardware starts to work on the IBs again.

Additional to that even after more than 5 years of developing this feature it 
is still not stable and we have massively problems getting the reference counts 
right.

As discussed with user space developers this behavior is not helpful in the 
first place. For graphics and multimedia workloads it makes much more sense to 
either completely re-create the context or at least re-submitting the IBs from 
userspace.

For compute use cases re-submitting is also not very helpful since userspace 
must rely on the accuracy of the result.

Because of this we stop this practice and instead just properly note that the 
fence submission was canceled. The only use case we keep the re-submission for 
now is SRIOV and function level resets.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d4584e577b51..39e94feba1ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5288,7 +5288,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 continue;

 /* No point to resubmit jobs if we didn't HW reset*/
-   if (!tmp_adev->asic_reset_res && !job_signaled)
+   if (!tmp_adev->asic_reset_res && !job_signaled &&
+   amdgpu_sriov_vf(tmp_adev))
 drm_sched_resubmit_jobs(>sched);

 drm_sched_start(>sched, 
!tmp_adev->asic_reset_res);
--
2.25.1





Re: [PATCH v5 19/19] drm/i915/vm_bind: Render VM_BIND documentation

2022-10-26 Thread Matthew Auld

On 25/10/2022 07:59, Niranjana Vishwanathapura wrote:

Update i915 documentation to include VM_BIND changes
and render all VM_BIND related documentation.

Signed-off-by: Niranjana Vishwanathapura 


Thanks for adding this,
Reviewed-by: Matthew Auld 


Re: [PATCH v5 09/19] drm/i915/vm_bind: Add out fence support

2022-10-26 Thread Matthew Auld

On 25/10/2022 07:58, Niranjana Vishwanathapura wrote:

Add support for handling out fence for vm_bind call.

v2: Reset vma->vm_bind_fence.syncobj to NULL at the end
 of vm_bind call.
v3: Remove vm_unbind out fence uapi which is not supported yet.
v4: Return error if I915_TIMELINE_FENCE_WAIT fence flag is set.
 Wait for bind to complete iff I915_TIMELINE_FENCE_SIGNAL is
 not specified.

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Andi Shyti 
---
  drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h   |  4 +
  .../drm/i915/gem/i915_gem_vm_bind_object.c| 93 +++
  drivers/gpu/drm/i915/i915_vma.c   |  7 +-
  drivers/gpu/drm/i915/i915_vma_types.h |  7 ++
  include/uapi/drm/i915_drm.h   | 49 +-
  5 files changed, 157 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h 
b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
index 36262a6357b5..b70e900e35ab 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h
@@ -8,6 +8,7 @@
  
  #include 
  
+struct dma_fence;

  struct drm_device;
  struct drm_file;
  struct i915_address_space;
@@ -23,4 +24,7 @@ int i915_gem_vm_unbind_ioctl(struct drm_device *dev, void 
*data,
  
  void i915_gem_vm_unbind_all(struct i915_address_space *vm);
  
+void i915_vm_bind_signal_fence(struct i915_vma *vma,

+  struct dma_fence * const fence);
+
  #endif /* __I915_GEM_VM_BIND_H */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c 
b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
index 863bd17c9253..fca6d6eb9ef8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c
@@ -7,6 +7,8 @@
  
  #include 
  
+#include 

+
  #include "gem/i915_gem_context.h"
  #include "gem/i915_gem_vm_bind.h"
  
@@ -100,6 +102,76 @@ static void i915_gem_vm_bind_remove(struct i915_vma *vma, bool release_obj)

i915_gem_object_put(vma->obj);
  }
  
+static int i915_vm_bind_add_fence(struct drm_file *file, struct i915_vma *vma,

+ u32 handle, u64 point)
+{
+   struct drm_syncobj *syncobj;
+
+   syncobj = drm_syncobj_find(file, handle);
+   if (!syncobj) {
+   DRM_DEBUG("Invalid syncobj handle provided\n");


AFAIK drm_dbg() is preferred, if possible.


+   return -ENOENT;
+   }
+
+   /*
+* For timeline syncobjs we need to preallocate chains for
+* later signaling.
+*/
+   if (point) {
+   vma->vm_bind_fence.chain_fence = dma_fence_chain_alloc();
+   if (!vma->vm_bind_fence.chain_fence) {
+   drm_syncobj_put(syncobj);
+   return -ENOMEM;
+   }
+   } else {
+   vma->vm_bind_fence.chain_fence = NULL;
+   }
+   vma->vm_bind_fence.syncobj = syncobj;
+   vma->vm_bind_fence.value = point;
+
+   return 0;
+}
+
+static void i915_vm_bind_put_fence(struct i915_vma *vma)
+{
+   if (!vma->vm_bind_fence.syncobj)
+   return;
+
+   drm_syncobj_put(vma->vm_bind_fence.syncobj);
+   dma_fence_chain_free(vma->vm_bind_fence.chain_fence);
+   vma->vm_bind_fence.syncobj = NULL;
+}
+
+/**
+ * i915_vm_bind_signal_fence() - Add fence to vm_bind syncobj
+ * @vma: vma mapping requiring signaling
+ * @fence: fence to be added
+ *
+ * Associate specified @fence with the @vma's syncobj to be
+ * signaled after the @fence work completes.
+ */
+void i915_vm_bind_signal_fence(struct i915_vma *vma,
+  struct dma_fence * const fence)
+{
+   struct drm_syncobj *syncobj = vma->vm_bind_fence.syncobj;
+
+   if (!syncobj)
+   return;
+
+   if (vma->vm_bind_fence.chain_fence) {
+   drm_syncobj_add_point(syncobj,
+ vma->vm_bind_fence.chain_fence,
+ fence, vma->vm_bind_fence.value);
+   /*
+* The chain's ownership is transferred to the
+* timeline.
+*/
+   vma->vm_bind_fence.chain_fence = NULL;
+   } else {
+   drm_syncobj_replace_fence(syncobj, fence);
+   }
+}
+
  static int i915_gem_vm_unbind_vma(struct i915_address_space *vm,
  struct drm_i915_gem_vm_unbind *va)
  {
@@ -205,6 +277,10 @@ static int i915_gem_vm_bind_obj(struct i915_address_space 
*vm,
if (!va->length || !IS_ALIGNED(va->start, I915_GTT_PAGE_SIZE))
ret = -EINVAL;
  
+	/* In fences are not supported */

+   if (va->fence.flags & I915_TIMELINE_FENCE_WAIT)
+   ret = -EINVAL;


I guess also:

if (flags & __I915_TIMELINE_FENCE_UNKNOWN_FLAGS)

Reviewed-by: Matthew Auld 


+
obj = i915_gem_object_lookup(file, va->handle);
if (!obj)
return -ENOENT;
@@ -237,6 

Re: [PATCH v5 16/19] drm/i915/vm_bind: userptr dma-resv changes

2022-10-26 Thread Matthew Auld

On 25/10/2022 07:59, Niranjana Vishwanathapura wrote:

For persistent (vm_bind) vmas of userptr BOs, handle the user
page pinning by using the i915_gem_object_userptr_submit_init()
/done() functions

v2: Do not double add vma to vm->userptr_invalidated_list

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Andi Shyti 

Reviewed-by: Matthew Auld 


[PATCH v3] drm: Move radeon and amdgpu Kconfig options into their directories

2022-10-26 Thread Andrew Davis
Most Kconfig options to enable a driver are in the Kconfig file
inside the relevant directory, move these two to the same.

Signed-off-by: Andrew Davis 
Reviewed-by: Christian König 
---

Changes from v2:
 - Rebased on latest

Changes from v1:
 - Fix whitespace issue pointed out by Randy

 drivers/gpu/drm/Kconfig| 57 --
 drivers/gpu/drm/amd/amdgpu/Kconfig | 29 +++
 drivers/gpu/drm/radeon/Kconfig | 30 
 3 files changed, 59 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index fa986075e8fb..9c2d9495cb3c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -233,65 +233,8 @@ source "drivers/gpu/drm/i2c/Kconfig"
 
 source "drivers/gpu/drm/arm/Kconfig"
 
-config DRM_RADEON
-   tristate "ATI Radeon"
-   depends on DRM && PCI && MMU
-   depends on AGP || !AGP
-   select FW_LOADER
-   select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HELPER
-select DRM_KMS_HELPER
-select DRM_TTM
-   select DRM_TTM_HELPER
-   select SND_HDA_COMPONENT if SND_HDA_CORE
-   select POWER_SUPPLY
-   select HWMON
-   select BACKLIGHT_CLASS_DEVICE
-   select INTERVAL_TREE
-   # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
-   # ACPI_VIDEO's dependencies must also be selected.
-   select INPUT if ACPI
-   select ACPI_VIDEO if ACPI
-   # On x86 ACPI_VIDEO also needs ACPI_WMI
-   select X86_PLATFORM_DEVICES if ACPI && X86
-   select ACPI_WMI if ACPI && X86
-   help
- Choose this option if you have an ATI Radeon graphics card.  There
- are both PCI and AGP versions.  You don't need to choose this to
- run the Radeon in plain VGA mode.
-
- If M is selected, the module will be called radeon.
-
 source "drivers/gpu/drm/radeon/Kconfig"
 
-config DRM_AMDGPU
-   tristate "AMD GPU"
-   depends on DRM && PCI && MMU
-   select FW_LOADER
-   select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HDMI_HELPER
-   select DRM_DISPLAY_HELPER
-   select DRM_KMS_HELPER
-   select DRM_SCHED
-   select DRM_TTM
-   select DRM_TTM_HELPER
-   select POWER_SUPPLY
-   select HWMON
-   select BACKLIGHT_CLASS_DEVICE
-   select INTERVAL_TREE
-   select DRM_BUDDY
-   # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
-   # ACPI_VIDEO's dependencies must also be selected.
-   select INPUT if ACPI
-   select ACPI_VIDEO if ACPI
-   # On x86 ACPI_VIDEO also needs ACPI_WMI
-   select X86_PLATFORM_DEVICES if ACPI && X86
-   select ACPI_WMI if ACPI && X86
-   help
- Choose this option if you have a recent AMD Radeon graphics card.
-
- If M is selected, the module will be called amdgpu.
-
 source "drivers/gpu/drm/amd/amdgpu/Kconfig"
 
 source "drivers/gpu/drm/nouveau/Kconfig"
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig 
b/drivers/gpu/drm/amd/amdgpu/Kconfig
index d55275de..5fcd510f1abb 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -1,4 +1,33 @@
 # SPDX-License-Identifier: MIT
+
+config DRM_AMDGPU
+   tristate "AMD GPU"
+   depends on DRM && PCI && MMU
+   select FW_LOADER
+   select DRM_DISPLAY_DP_HELPER
+   select DRM_DISPLAY_HDMI_HELPER
+   select DRM_DISPLAY_HELPER
+   select DRM_KMS_HELPER
+   select DRM_SCHED
+   select DRM_TTM
+   select DRM_TTM_HELPER
+   select POWER_SUPPLY
+   select HWMON
+   select BACKLIGHT_CLASS_DEVICE
+   select INTERVAL_TREE
+   select DRM_BUDDY
+   # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
+   # ACPI_VIDEO's dependencies must also be selected.
+   select INPUT if ACPI
+   select ACPI_VIDEO if ACPI
+   # On x86 ACPI_VIDEO also needs ACPI_WMI
+   select X86_PLATFORM_DEVICES if ACPI && X86
+   select ACPI_WMI if ACPI && X86
+   help
+ Choose this option if you have a recent AMD Radeon graphics card.
+
+ If M is selected, the module will be called amdgpu.
+
 config DRM_AMDGPU_SI
bool "Enable amdgpu support for SI parts"
depends on DRM_AMDGPU
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 52819e7f1fca..2267c501f724 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,4 +1,34 @@
 # SPDX-License-Identifier: MIT
+
+config DRM_RADEON
+   tristate "ATI Radeon"
+   depends on DRM && PCI && MMU
+   depends on AGP || !AGP
+   select FW_LOADER
+   select DRM_DISPLAY_DP_HELPER
+   select DRM_DISPLAY_HELPER
+   select DRM_KMS_HELPER
+   select DRM_TTM
+   select DRM_TTM_HELPER
+   select SND_HDA_COMPONENT if SND_HDA_CORE
+   select POWER_SUPPLY
+   select HWMON
+   select BACKLIGHT_CLASS_DEVICE
+   select INTERVAL_TREE
+   

Re: [PATCH v4 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-26 Thread maxime
Hi Dave,

On Wed, Oct 26, 2022 at 05:00:25PM +0100, Dave Stevenson wrote:
> > +
> > +   node = rpi_firmware_find_node();
> > +   if (!node)
> > +   return -EINVAL;
> > +
> > +   firmware = rpi_firmware_get(node);
> > +   of_node_put(node);
> > +   if (!firmware)
> > +   return -EPROBE_DEFER;
> > +
> > hvs->core_clk = devm_clk_get(>dev, NULL);
> > if (IS_ERR(hvs->core_clk)) {
> > dev_err(>dev, "Couldn't get core clock\n");
> > return PTR_ERR(hvs->core_clk);
> > }
> >
> > +   max_rate = rpi_firmware_clk_get_max_rate(firmware,
> > +
> > RPI_FIRMWARE_CORE_CLK_ID);
> > +   rpi_firmware_put(firmware);
> > +   if (max_rate >= 55000)
> > +   hvs->vc5_hdmi_enable_scrambling = true;
> > +
> > +   hvs->max_core_rate = max_rate;
> 
> I was going to query the reason for storing this value, but it's used
> when we get to patch 7/7.
> I won't quibble about having it as an unused value for 2 patches.

Yeah, it felt natural to do it in that patch, even though it's indeed
only useful in a couple of patches.

Maxime


Re: [PATCH v4 4/7] drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection

2022-10-26 Thread maxime
Hi Dave,

Thanks for your review

On Wed, Oct 26, 2022 at 04:36:04PM +0100, Dave Stevenson wrote:
> On Wed, 26 Oct 2022 at 16:27, Dave Stevenson
>  wrote:
> >
> > On Thu, 20 Oct 2022 at 10:14,  wrote:
> > >
> > > In order to support higher HDMI frequencies, users have to set the
> > > hdmi_enable_4kp60 parameter in their config.txt file.
> > >
> > > We were detecting this so far by calling clk_round_rate() on the core
> > > clock with the frequency we're supposed to run at when one of those
> > > modes is enabled. Whether or not the parameter was enabled could then be
> > > inferred by the returned rate since the maximum clock rate reported by
> > > the firmware was one of the side effect of setting that parameter.
> > >
> > > However, the recent clock rework we did changed what clk_round_rate()
> > > was returning to always return the minimum allowed, and thus this test
> > > wasn't reliable anymore.
> > >
> > > Let's use the new clk_get_max_rate() function to reliably determine the
> > > maximum rate allowed on that clock and fix the 4k@60Hz output.
> > >
> > > Fixes: e9d6cea2af1c ("clk: bcm: rpi: Run some clocks at the minimum rate 
> > > allowed")
> > > Signed-off-by: Maxime Ripard 
> >
> > Reviewed-by: Dave Stevenson 
> >
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c 
> > > b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > > index 64f9feabf43e..87961d4de5aa 100644
> > > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > > @@ -46,6 +46,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >  #include 
> > >  #include 
> > >  #include 
> > > @@ -3429,7 +3430,7 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> > > device *master, void *data)
> > >
> > > if (variant->max_pixel_clock == 6) {
> > > struct vc4_dev *vc4 = to_vc4_dev(drm);
> > > -   long max_rate = clk_round_rate(vc4->hvs->core_clk, 
> > > 55000);
> > > +   unsigned long max_rate = 
> > > rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
> 
> Actually minor nit:
> rpi_firmware_clk_get_max_rate returns an unsigned int.
> AFAICT we don't need the range of unsigned long in any subsequent
> code, so I think it could just be unsigned int here.
> 
> clk_round_rate returned a long, and therefore previously it did have to be 
> that.

Yeah, I was actually two-minded about this.
rpi_firmware_clk_get_max_rate() indeed returns an unsigned long, because
that's what the firmware returns.

But the clock framework uses unsigned long to store all its frequencies,
and in our case here in clk_set_min_rate().

I don't mind changing it to unsigned int here if you prefer to, and if
you're fine with the rest of the patches I can fix it up while applying
the patches.

Maxime


RE: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

2022-10-26 Thread Liu, Shaoyun
[AMD Official Use Only - General]

The  user space  shouldn't care about  SRIOV or not ,  I don't think we need to 
keep the re-submission for SRIOV as well.  The reset from SRIOV could trigger 
the  host do a whole GPU reset which will have the same issue as bare metal.

Regards
Shaoyun.liu

-Original Message-
From: amd-gfx  On Behalf Of Christian 
König
Sent: Wednesday, October 26, 2022 11:36 AM
To: Tuikov, Luben ; Prosyak, Vitaly 
; Deucher, Alexander ; 
daniel.vet...@ffwll.ch; amd-...@lists.freedesktop.org; 
dri-devel@lists.freedesktop.org
Cc: Koenig, Christian 
Subject: [PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

Re-submitting IBs by the kernel has many problems because pre- requisite state 
is not automatically re-created as well. In other words neither binary 
semaphores nor things like ring buffer pointers are in the state they should be 
when the hardware starts to work on the IBs again.

Additional to that even after more than 5 years of developing this feature it 
is still not stable and we have massively problems getting the reference counts 
right.

As discussed with user space developers this behavior is not helpful in the 
first place. For graphics and multimedia workloads it makes much more sense to 
either completely re-create the context or at least re-submitting the IBs from 
userspace.

For compute use cases re-submitting is also not very helpful since userspace 
must rely on the accuracy of the result.

Because of this we stop this practice and instead just properly note that the 
fence submission was canceled. The only use case we keep the re-submission for 
now is SRIOV and function level resets.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d4584e577b51..39e94feba1ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5288,7 +5288,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
continue;

/* No point to resubmit jobs if we didn't HW reset*/
-   if (!tmp_adev->asic_reset_res && !job_signaled)
+   if (!tmp_adev->asic_reset_res && !job_signaled &&
+   amdgpu_sriov_vf(tmp_adev))
drm_sched_resubmit_jobs(>sched);

drm_sched_start(>sched, 
!tmp_adev->asic_reset_res);
--
2.25.1



Re: [PATCH v4 7/7] drm/vc4: Make sure we don't end up with a core clock too high

2022-10-26 Thread Dave Stevenson
On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> Following the clock rate range improvements to the clock framework,
> trying to set a disjoint range on a clock will now result in an error.
>
> Thus, we can't set a minimum rate higher than the maximum reported by
> the firmware, or clk_set_min_rate() will fail.
>
> Thus we need to clamp the rate we are about to ask for to the maximum
> rate possible on that clock.
>
> Signed-off-by: Maxime Ripard 

Thanks Maxime.

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_kms.c | 13 -
>  1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 4419e810103d..5c97642ed66a 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -396,8 +396,8 @@ static void vc4_atomic_commit_tail(struct 
> drm_atomic_state *state)
> if (vc4->is_vc5) {
> unsigned long state_rate = max(old_hvs_state->core_clock_rate,
>
> new_hvs_state->core_clock_rate);
> -   unsigned long core_rate = max_t(unsigned long,
> -   5, state_rate);
> +   unsigned long core_rate = clamp_t(unsigned long, state_rate,
> + 5, 
> hvs->max_core_rate);
>
> drm_dbg(dev, "Raising the core clock at %lu Hz\n", core_rate);
>
> @@ -431,14 +431,17 @@ static void vc4_atomic_commit_tail(struct 
> drm_atomic_state *state)
> drm_atomic_helper_cleanup_planes(dev, state);
>
> if (vc4->is_vc5) {
> -   drm_dbg(dev, "Running the core clock at %lu Hz\n",
> -   new_hvs_state->core_clock_rate);
> +   unsigned long core_rate = min_t(unsigned long,
> +   hvs->max_core_rate,
> +   
> new_hvs_state->core_clock_rate);
> +
> +   drm_dbg(dev, "Running the core clock at %lu Hz\n", core_rate);
>
> /*
>  * Request a clock rate based on the current HVS
>  * requirements.
>  */
> -   WARN_ON(clk_set_min_rate(hvs->core_clk, 
> new_hvs_state->core_clock_rate));
> +   WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate));
>
> drm_dbg(dev, "Core clock actual rate: %lu Hz\n",
> clk_get_rate(hvs->core_clk));
>
> --
> b4 0.10.1


Re: [PATCH v4 6/7] drm/vc4: hdmi: Add more checks for 4k resolutions

2022-10-26 Thread Dave Stevenson
On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> From: Dom Cobley 
>
> At least the 4096x2160@60Hz mode requires some overclocking that isn't
> available by default, even if hdmi_enable_4kp60 is enabled.
>
> Let's add some logic to detect whether we can satisfy the core clock
> requirements for that mode, and prevent it from being used otherwise.
>
> Signed-off-by: Dom Cobley 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_drv.h  |  6 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 11 +--
>  drivers/gpu/drm/vc4/vc4_hvs.c  |  3 +++
>  3 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 8b2b1af565f9..72a6b7151d23 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -347,6 +347,12 @@ struct vc4_hvs {
>  * available.
>  */
> bool vc5_hdmi_enable_scrambling;
> +
> +   /*
> +* 4096x2160@60 requires a core overclock to work, so register
> +* whether that is sufficient.
> +*/
> +   bool vc5_hdmi_enable_4096by2160;
>  };
>
>  struct vc4_plane {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index afe3daa2173e..fd3730ea976f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1753,6 +1753,7 @@ vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi 
> *vc4_hdmi,
>
>  static enum drm_mode_status
>  vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
> +const struct drm_display_mode *mode,
>  unsigned long long clock)
>  {
> const struct drm_connector *connector = _hdmi->connector;
> @@ -1765,6 +1766,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> *vc4_hdmi,
> if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> HDMI_14_MAX_TMDS_CLK)
> return MODE_CLOCK_HIGH;
>
> +   /* 4096x2160@60 is not reliable without overclocking core */
> +   if (!vc4->hvs->vc5_hdmi_enable_4096by2160 &&
> +   mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
> +   drm_mode_vrefresh(mode) >= 50)
> +   return MODE_CLOCK_HIGH;
> +
> if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> return MODE_CLOCK_HIGH;
>
> @@ -1799,7 +1806,7 @@ vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi 
> *vc4_hdmi,
> unsigned long long clock;
>
> clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
> -   if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK)
> +   if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK)
> return -EINVAL;
>
> vc4_state->tmds_char_rate = clock;
> @@ -1962,7 +1969,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>  (mode->hsync_end % 2) || (mode->htotal % 2)))
> return MODE_H_ILLEGAL;
>
> -   return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000);
> +   return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 
> 1000);
>  }
>
>  static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = 
> {
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 300ac0b57571..a68913f76687 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -818,6 +818,9 @@ static int vc4_hvs_bind(struct device *dev, struct device 
> *master, void *data)
> if (max_rate >= 55000)
> hvs->vc5_hdmi_enable_scrambling = true;
>
> +   if (max_rate >= 6)
> +   hvs->vc5_hdmi_enable_4096by2160 = true;
> +
> hvs->max_core_rate = max_rate;
>
> ret = clk_prepare_enable(hvs->core_clk);
>
> --
> b4 0.10.1


Re: [PATCH v4 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-26 Thread Dave Stevenson
I knew there was something else

On Wed, 26 Oct 2022 at 17:00, Dave Stevenson
 wrote:
>
> Hi Maxime
>
> On Thu, 20 Oct 2022 at 10:14,  wrote:
> >
> > In order to support higher HDMI frequencies, users have to set the
> > hdmi_enable_4kp60 parameter in their config.txt file.
> >
> > This will have the side-effect of raising the maximum of the core clock,
> > tied to the HVS, and managed by the HVS driver.
> >
> > However, we are querying this in the HDMI driver by poking into the HVS
> > structure to get our struct clk handle.
> >
> > Let's make this part of the HVS bind implementation to have all the core
> > clock related setup in the same place.
> >
> > Signed-off-by: Maxime Ripard 
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h  | 10 ++
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  8 
> >  drivers/gpu/drm/vc4/vc4_hvs.c  | 23 +++
> >  4 files changed, 37 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index 418a8242691f..8b2b1af565f9 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -326,6 +326,8 @@ struct vc4_hvs {
> >
> > struct clk *core_clk;
> >
> > +   unsigned long max_core_rate;
> > +
> > /* Memory manager for CRTCs to allocate space in the display
> >  * list.  Units are dwords.
> >  */
> > @@ -337,6 +339,14 @@ struct vc4_hvs {
> > struct drm_mm_node mitchell_netravali_filter;
> >
> > struct debugfs_regset32 regset;
> > +
> > +   /*
> > +* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> > +* rate higher than 297MHz, it needs some adjustments in the
> > +* config.txt file to be able to do so and thus won't always be
> > +* available.
> > +*/
> > +   bool vc5_hdmi_enable_scrambling;

Name only. This flag isn't to do with scrambling, it's whether we can
achieve pixel rates greater than those defined by HDMI 1.4.

We do have code related to enabling scrambling, which is part of HDMI
2.0, so this currently could cause confusion.

  Dave

> >  };
> >
> >  struct vc4_plane {
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 87961d4de5aa..afe3daa2173e 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -46,7 +46,6 @@
> >  #include 
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -460,6 +459,7 @@ static int vc4_hdmi_connector_detect_ctx(struct 
> > drm_connector *connector,
> >  static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
> >  {
> > struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
> > +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> > int ret = 0;
> > struct edid *edid;
> >
> > @@ -483,7 +483,7 @@ static int vc4_hdmi_connector_get_modes(struct 
> > drm_connector *connector)
> > ret = drm_add_edid_modes(connector, edid);
> > kfree(edid);
> >
> > -   if (vc4_hdmi->disable_4kp60) {
> > +   if (!vc4->hvs->vc5_hdmi_enable_scrambling) {
> > struct drm_device *drm = connector->dev;
> > const struct drm_display_mode *mode;
> >
> > @@ -1757,11 +1757,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> > *vc4_hdmi,
> >  {
> > const struct drm_connector *connector = _hdmi->connector;
> > const struct drm_display_info *info = >display_info;
> > +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> >
> > if (clock > vc4_hdmi->variant->max_pixel_clock)
> > return MODE_CLOCK_HIGH;
> >
> > -   if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
> > +   if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> > HDMI_14_MAX_TMDS_CLK)
> > return MODE_CLOCK_HIGH;
> >
> > if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> > @@ -3428,14 +3429,6 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> > device *master, void *data)
> > vc4_hdmi->disable_wifi_frequencies =
> > of_property_read_bool(dev->of_node, 
> > "wifi-2.4ghz-coexistence");
> >
> > -   if (variant->max_pixel_clock == 6) {
> > -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> > -   unsigned long max_rate = 
> > rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
> > -
> > -   if (max_rate < 55000)
> > -   vc4_hdmi->disable_4kp60 = true;
> > -   }
> > -
> > ret = devm_pm_runtime_enable(dev);
> > if (ret)
> > return ret;
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > index db823efb2563..e3619836ca17 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > @@ -156,14 +156,6 @@ struct 

Re: [PATCH v4 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-26 Thread Dave Stevenson
Hi Maxime

On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> In order to support higher HDMI frequencies, users have to set the
> hdmi_enable_4kp60 parameter in their config.txt file.
>
> This will have the side-effect of raising the maximum of the core clock,
> tied to the HVS, and managed by the HVS driver.
>
> However, we are querying this in the HDMI driver by poking into the HVS
> structure to get our struct clk handle.
>
> Let's make this part of the HVS bind implementation to have all the core
> clock related setup in the same place.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h  | 10 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ---
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  8 
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 23 +++
>  4 files changed, 37 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 418a8242691f..8b2b1af565f9 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -326,6 +326,8 @@ struct vc4_hvs {
>
> struct clk *core_clk;
>
> +   unsigned long max_core_rate;
> +
> /* Memory manager for CRTCs to allocate space in the display
>  * list.  Units are dwords.
>  */
> @@ -337,6 +339,14 @@ struct vc4_hvs {
> struct drm_mm_node mitchell_netravali_filter;
>
> struct debugfs_regset32 regset;
> +
> +   /*
> +* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> +* rate higher than 297MHz, it needs some adjustments in the
> +* config.txt file to be able to do so and thus won't always be
> +* available.
> +*/
> +   bool vc5_hdmi_enable_scrambling;
>  };
>
>  struct vc4_plane {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 87961d4de5aa..afe3daa2173e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -46,7 +46,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -460,6 +459,7 @@ static int vc4_hdmi_connector_detect_ctx(struct 
> drm_connector *connector,
>  static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>  {
> struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> int ret = 0;
> struct edid *edid;
>
> @@ -483,7 +483,7 @@ static int vc4_hdmi_connector_get_modes(struct 
> drm_connector *connector)
> ret = drm_add_edid_modes(connector, edid);
> kfree(edid);
>
> -   if (vc4_hdmi->disable_4kp60) {
> +   if (!vc4->hvs->vc5_hdmi_enable_scrambling) {
> struct drm_device *drm = connector->dev;
> const struct drm_display_mode *mode;
>
> @@ -1757,11 +1757,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> *vc4_hdmi,
>  {
> const struct drm_connector *connector = _hdmi->connector;
> const struct drm_display_info *info = >display_info;
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
>
> if (clock > vc4_hdmi->variant->max_pixel_clock)
> return MODE_CLOCK_HIGH;
>
> -   if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
> +   if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> HDMI_14_MAX_TMDS_CLK)
> return MODE_CLOCK_HIGH;
>
> if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> @@ -3428,14 +3429,6 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> device *master, void *data)
> vc4_hdmi->disable_wifi_frequencies =
> of_property_read_bool(dev->of_node, 
> "wifi-2.4ghz-coexistence");
>
> -   if (variant->max_pixel_clock == 6) {
> -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> -   unsigned long max_rate = 
> rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
> -
> -   if (max_rate < 55000)
> -   vc4_hdmi->disable_4kp60 = true;
> -   }
> -
> ret = devm_pm_runtime_enable(dev);
> if (ret)
> return ret;
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index db823efb2563..e3619836ca17 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -156,14 +156,6 @@ struct vc4_hdmi {
>  */
> bool disable_wifi_frequencies;
>
> -   /*
> -* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> -* rate higher than 297MHz, it needs some adjustments in the
> -* config.txt file to be able to do so and thus won't always be
> -* available.
> -*/
> -   bool disable_4kp60;
> -
> struct cec_adapter *cec_adap;
> struct cec_msg cec_rx_msg;
> bool cec_tx_ok;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ac9f5a2d5f9..300ac0b57571 100644

[PATCH drm-misc-next v3 3/5] drm/arm/malidp: crtc: use drmm_crtc_init_with_planes()

2022-10-26 Thread Danilo Krummrich
Use drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes()
to get rid of the explicit destroy hook in struct drm_plane_funcs.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/malidp_crtc.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 34ad7e1cd2b8..dc01c43f6193 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -514,7 +514,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc 
*crtc)
 }
 
 static const struct drm_crtc_funcs malidp_crtc_funcs = {
-   .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.reset = malidp_crtc_reset,
@@ -548,8 +547,8 @@ int malidp_crtc_init(struct drm_device *drm)
return -EINVAL;
}
 
-   ret = drm_crtc_init_with_planes(drm, >crtc, primary, NULL,
-   _crtc_funcs, NULL);
+   ret = drmm_crtc_init_with_planes(drm, >crtc, primary, NULL,
+_crtc_funcs, NULL);
if (ret)
return ret;
 
-- 
2.37.3



[PATCH drm-misc-next v3 1/5] drm/arm/malidp: use drmm_* to allocate driver structures

2022-10-26 Thread Danilo Krummrich
Use drm managed resources to allocate driver structures and get rid of
the deprecated drm_dev_alloc() call and replace it with
devm_drm_dev_alloc().

This also serves as preparation to get rid of drm_device->dev_private
and to fix use-after-free issues on driver unload.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/malidp_drv.c | 20 +++-
 drivers/gpu/drm/arm/malidp_drv.h |  1 +
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 1d0b0c54ccc7..41c80e905991 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -716,11 +717,13 @@ static int malidp_bind(struct device *dev)
int ret = 0, i;
u32 version, out_depth = 0;
 
-   malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL);
-   if (!malidp)
-   return -ENOMEM;
+   malidp = devm_drm_dev_alloc(dev, _driver, typeof(*malidp), base);
+   if (IS_ERR(malidp))
+   return PTR_ERR(malidp);
+
+   drm = >base;
 
-   hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL);
+   hwdev = drmm_kzalloc(drm, sizeof(*hwdev), GFP_KERNEL);
if (!hwdev)
return -ENOMEM;
 
@@ -753,12 +756,6 @@ static int malidp_bind(struct device *dev)
if (ret && ret != -ENODEV)
return ret;
 
-   drm = drm_dev_alloc(_driver, dev);
-   if (IS_ERR(drm)) {
-   ret = PTR_ERR(drm);
-   goto alloc_fail;
-   }
-
drm->dev_private = malidp;
dev_set_drvdata(dev, drm);
 
@@ -887,8 +884,6 @@ static int malidp_bind(struct device *dev)
malidp_runtime_pm_suspend(dev);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
-   drm_dev_put(drm);
-alloc_fail:
of_reserved_mem_device_release(dev);
 
return ret;
@@ -917,7 +912,6 @@ static void malidp_unbind(struct device *dev)
malidp_runtime_pm_suspend(dev);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
-   drm_dev_put(drm);
of_reserved_mem_device_release(dev);
 }
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index cdfddfabf2d1..00be369b28f1 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -29,6 +29,7 @@ struct malidp_error_stats {
 };
 
 struct malidp_drm {
+   struct drm_device base;
struct malidp_hw_device *dev;
struct drm_crtc crtc;
struct drm_writeback_connector mw_connector;
-- 
2.37.3



[PATCH drm-misc-next v3 5/5] drm/arm/malidp: remove calls to drm_mode_config_cleanup()

2022-10-26 Thread Danilo Krummrich
drm_mode_config_init() simply calls drmm_mode_config_init(), hence
cleanup is automatically handled through registering
drm_mode_config_cleanup() with drmm_add_action_or_reset().

While at it, get rid of the deprecated drm_mode_config_init() and
replace it with drmm_mode_config_init() directly.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/malidp_drv.c | 20 ++--
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 678c5b0d8014..bebaa5a07e27 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -396,7 +396,9 @@ static int malidp_init(struct drm_device *drm)
struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
 
-   drm_mode_config_init(drm);
+   ret = drmm_mode_config_init(drm);
+   if (ret)
+   goto out;
 
drm->mode_config.min_width = hwdev->min_line_size;
drm->mode_config.min_height = hwdev->min_line_size;
@@ -407,24 +409,16 @@ static int malidp_init(struct drm_device *drm)
 
ret = malidp_crtc_init(drm);
if (ret)
-   goto crtc_fail;
+   goto out;
 
ret = malidp_mw_connector_init(drm);
if (ret)
-   goto crtc_fail;
-
-   return 0;
+   goto out;
 
-crtc_fail:
-   drm_mode_config_cleanup(drm);
+out:
return ret;
 }
 
-static void malidp_fini(struct drm_device *drm)
-{
-   drm_mode_config_cleanup(drm);
-}
-
 static int malidp_irq_init(struct platform_device *pdev)
 {
int irq_de, irq_se, ret = 0;
@@ -874,7 +868,6 @@ static int malidp_bind(struct device *dev)
 bind_fail:
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
-   malidp_fini(drm);
 query_hw_fail:
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
@@ -902,7 +895,6 @@ static void malidp_unbind(struct device *dev)
component_unbind_all(dev, drm);
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
-   malidp_fini(drm);
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
-- 
2.37.3



[PATCH drm-misc-next v3 4/5] drm/arm/malidp: plane: use drm managed resources

2022-10-26 Thread Danilo Krummrich
Use drm managed resource allocation (drmm_universal_plane_alloc()) in
order to get rid of the explicit destroy hook in struct drm_plane_funcs.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/malidp_planes.c | 28 +++-
 1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_planes.c 
b/drivers/gpu/drm/arm/malidp_planes.c
index 815d9199752f..34547edf1ee3 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -68,14 +68,6 @@
 /* readahead for partial-frame prefetch */
 #define MALIDP_MMU_PREFETCH_READAHEAD  8
 
-static void malidp_de_plane_destroy(struct drm_plane *plane)
-{
-   struct malidp_plane *mp = to_malidp_plane(plane);
-
-   drm_plane_cleanup(plane);
-   kfree(mp);
-}
-
 /*
  * Replicate what the default ->reset hook does: free the state pointer and
  * allocate a new empty object. We just need enough space to store
@@ -260,7 +252,6 @@ static bool malidp_format_mod_supported_per_plane(struct 
drm_plane *plane,
 static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
-   .destroy = malidp_de_plane_destroy,
.reset = malidp_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state,
.atomic_destroy_state = malidp_destroy_plane_state,
@@ -972,12 +963,6 @@ int malidp_de_planes_init(struct drm_device *drm)
for (i = 0; i < map->n_layers; i++) {
u8 id = map->layers[i].id;
 
-   plane = kzalloc(sizeof(*plane), GFP_KERNEL);
-   if (!plane) {
-   ret = -ENOMEM;
-   goto cleanup;
-   }
-
/* build the list of DRM supported formats based on the map */
for (n = 0, j = 0;  j < map->n_pixel_formats; j++) {
if ((map->pixel_formats[j].layer & id) == id)
@@ -990,13 +975,14 @@ int malidp_de_planes_init(struct drm_device *drm)
/*
 * All the layers except smart layer supports AFBC modifiers.
 */
-   ret = drm_universal_plane_init(drm, >base, crtcs,
-   _de_plane_funcs, formats, n,
-   (id == DE_SMART) ? linear_only_modifiers : 
modifiers,
-   plane_type, NULL);
-
-   if (ret < 0)
+   plane = drmm_universal_plane_alloc(drm, struct malidp_plane, 
base,
+  crtcs, 
_de_plane_funcs, formats, n,
+  (id == DE_SMART) ? 
linear_only_modifiers :
+  modifiers, plane_type, NULL);
+   if (IS_ERR(plane)) {
+   ret = PTR_ERR(plane);
goto cleanup;
+   }
 
drm_plane_helper_add(>base,
 _de_plane_helper_funcs);
-- 
2.37.3



[PATCH drm-misc-next v3 2/5] drm/arm/malidp: replace drm->dev_private with drm_to_malidp()

2022-10-26 Thread Danilo Krummrich
Using drm_device->dev_private is deprecated. Since we've switched to
devm_drm_dev_alloc(), struct drm_device is now embedded in struct
malidp_drm, hence we can use container_of() to get the struct drm_device
instance instead.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/malidp_crtc.c   |  2 +-
 drivers/gpu/drm/arm/malidp_drv.c| 29 +
 drivers/gpu/drm/arm/malidp_drv.h|  1 +
 drivers/gpu/drm/arm/malidp_hw.c | 10 +-
 drivers/gpu/drm/arm/malidp_mw.c |  6 +++---
 drivers/gpu/drm/arm/malidp_planes.c |  4 ++--
 6 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 962730772b2f..34ad7e1cd2b8 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -526,7 +526,7 @@ static const struct drm_crtc_funcs malidp_crtc_funcs = {
 
 int malidp_crtc_init(struct drm_device *drm)
 {
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
struct drm_plane *primary = NULL, *plane;
int ret;
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 41c80e905991..678c5b0d8014 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -169,7 +169,7 @@ static void malidp_atomic_commit_se_config(struct drm_crtc 
*crtc,
  */
 static int malidp_set_and_wait_config_valid(struct drm_device *drm)
 {
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
int ret;
 
@@ -190,7 +190,7 @@ static int malidp_set_and_wait_config_valid(struct 
drm_device *drm)
 static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
 {
struct drm_device *drm = state->dev;
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
int loop = 5;
 
malidp->event = malidp->crtc.state->event;
@@ -231,7 +231,7 @@ static void malidp_atomic_commit_hw_done(struct 
drm_atomic_state *state)
 static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
 {
struct drm_device *drm = state->dev;
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
@@ -393,7 +393,7 @@ static const struct drm_mode_config_funcs 
malidp_mode_config_funcs = {
 static int malidp_init(struct drm_device *drm)
 {
int ret;
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
 
drm_mode_config_init(drm);
@@ -429,7 +429,7 @@ static int malidp_irq_init(struct platform_device *pdev)
 {
int irq_de, irq_se, ret = 0;
struct drm_device *drm = dev_get_drvdata(>dev);
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
 
/* fetch the interrupts from DT */
@@ -463,7 +463,7 @@ static int malidp_dumb_create(struct drm_file *file_priv,
  struct drm_device *drm,
  struct drm_mode_create_dumb *args)
 {
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
/* allocate for the worst case scenario, i.e. rotated buffers */
u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1);
 
@@ -509,7 +509,7 @@ static void malidp_error_stats_dump(const char *prefix,
 static int malidp_show_stats(struct seq_file *m, void *arg)
 {
struct drm_device *drm = m->private;
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
unsigned long irqflags;
struct malidp_error_stats de_errors, se_errors;
 
@@ -532,7 +532,7 @@ static ssize_t malidp_debugfs_write(struct file *file, 
const char __user *ubuf,
 {
struct seq_file *m = file->private_data;
struct drm_device *drm = m->private;
-   struct malidp_drm *malidp = drm->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(drm);
unsigned long irqflags;
 
spin_lock_irqsave(>errors_lock, irqflags);
@@ -553,7 +553,7 @@ static const struct file_operations malidp_debugfs_fops = {
 
 static void malidp_debugfs_init(struct drm_minor *minor)
 {
-   struct malidp_drm *malidp = minor->dev->dev_private;
+   struct malidp_drm *malidp = drm_to_malidp(minor->dev);
 
malidp_error_stats_init(>de_errors);
malidp_error_stats_init(>se_errors);
@@ -653,7 +653,7 @@ static ssize_t core_id_show(struct device *dev, struct 
device_attribute *attr,
char *buf)
 {
struct drm_device 

[PATCH drm-misc-next v3 0/5] drm/arm/malidp: use drm managed resources

2022-10-26 Thread Danilo Krummrich
Hi,

This patch series converts the driver to use drm managed resources to prevent
potential use-after-free issues on driver unbind/rebind and to get rid of the
usage of deprecated APIs.

Changes in v2:
  - While protecting critical sections with drm_dev_{enter,exit} I forgot to
handle alternate return paths within the read-side critical sections, hence
fix them.
  - Add a patch to remove explicit calls to drm_mode_config_cleanup() and switch
to drmm_mode_config_init() explicitly.

Changes in v3:
  - Remove patches to protect platform device bound resources with
drm_dev_{enter,exit}, since this would leave the hardware enabled when
regularly unloading the driver e.g. via rmmod.
Instead do this in a later series, once we got drm_dev_unplug() in place
to deal with a regular driver shutdown.

Danilo Krummrich (5):
  drm/arm/malidp: use drmm_* to allocate driver structures
  drm/arm/malidp: replace drm->dev_private with drm_to_malidp()
  drm/arm/malidp: crtc: use drmm_crtc_init_with_planes()
  drm/arm/malidp: plane: use drm managed resources
  drm/arm/malidp: remove calls to drm_mode_config_cleanup()

 drivers/gpu/drm/arm/malidp_crtc.c   |  7 ++-
 drivers/gpu/drm/arm/malidp_drv.c| 69 +++--
 drivers/gpu/drm/arm/malidp_drv.h|  2 +
 drivers/gpu/drm/arm/malidp_hw.c | 10 ++---
 drivers/gpu/drm/arm/malidp_mw.c |  6 +--
 drivers/gpu/drm/arm/malidp_planes.c | 32 -
 6 files changed, 48 insertions(+), 78 deletions(-)


base-commit: e1e7bc481d49c3e3ada11029ce0d9b85a0a539d7
-- 
2.37.3



[PATCH 3/5] drm/amdgpu: stop resubmittting jobs in amdgpu_pci_resume

2022-10-26 Thread Christian König
As far as I can see this is not really recoverable since a PCI reset
clears VRAM.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 39e94feba1ac..b1827e804363 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5745,8 +5745,6 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
if (!ring || !ring->sched.thread)
continue;
 
-
-   drm_sched_resubmit_jobs(>sched);
drm_sched_start(>sched, true);
}
 
-- 
2.25.1



[PATCH 3/3] drm: bridge: samsung-dsim: Select DSI HS clock rate from downstream bridge limits

2022-10-26 Thread Marek Vasut
In case the downstream bridge state reports DSI HS clock minimum and
maximum limits, find the most suitable DSI HS clock rate and use it
for the DSI link.

Signed-off-by: Marek Vasut 
---
Cc: Laurent Pinchart 
Cc: Lucas Stach 
Cc: Maxime Ripard 
Cc: Robert Foss 
Cc: Sam Ravnborg 
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c 
b/drivers/gpu/drm/bridge/samsung-dsim.c
index 9623923036292..697329d0faa35 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1399,7 +1399,41 @@ static int samsung_dsim_atomic_check(struct drm_bridge 
*bridge,
 {
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
struct drm_display_mode *adjusted_mode = _state->adjusted_mode;
+   struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge);
+   struct drm_bridge_state *next_bridge_state;
 
+   /* This DSIM bridge can produce HS clock in range of 12..750 MHz */
+   bridge_state->hs_rate_min = 12000;
+   bridge_state->hs_rate_max = 75;
+
+   if (next_bridge) {
+   next_bridge_state = 
drm_atomic_get_new_bridge_state(crtc_state->state,
+   
next_bridge);
+   /*
+* This bridge ability to provide HS clock does not overlap
+* with next bridge HS clock requirements, link constraints
+* are not met and link can not be operational.
+*/
+   if (bridge_state->hs_rate_max < next_bridge_state->hs_rate_min 
||
+   bridge_state->hs_rate_min > next_bridge_state->hs_rate_max)
+   goto exit;
+
+   /*
+* In case the nearest bridge specifies DSI HS clock rate
+* and supports DSI burst mode, run the DSI link at highest
+* supported DSI HS clock frequency to achieve the shortest
+* transfer bursts, longest time in LP mode between bursts,
+* and thus most power efficient transfer.
+*
+* Note that DSI HS clock lane frequency is
+* DSIM PLL output / 2 .
+*/
+   dsi->burst_clk_rate = min(bridge_state->hs_rate_max,
+ next_bridge_state->hs_rate_max) *
+ 2 * 1000;
+   }
+
+exit:
/*
 * The i.MX8M Mini/Nano glue logic between LCDIF and DSIM
 * inverts HS/VS/DE sync signals polarity, therefore, while
-- 
2.35.1



[PATCH 2/3] drm/bridge: tc358767: Report minimum and maximum DSI HS clock to upstream bridge

2022-10-26 Thread Marek Vasut
In case TC358767 operates in DSI-to-DPI mode and its clock are supplied
from XTal connected to RefClk, the range of supported input DSI HS clock
is limited.

Expose this limitation to the upstream bridge by providing minimum and
maximum accepted DSI HS clock frequency via bridge state.

Signed-off-by: Marek Vasut 
---
Cc: Laurent Pinchart 
Cc: Lucas Stach 
Cc: Maxime Ripard 
Cc: Robert Foss 
Cc: Sam Ravnborg 
---
 drivers/gpu/drm/bridge/tc358767.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/bridge/tc358767.c 
b/drivers/gpu/drm/bridge/tc358767.c
index b5f4e5328eaf9..3f423a29c703b 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1516,10 +1516,34 @@ static int tc_dpi_atomic_check(struct drm_bridge 
*bridge,
   struct drm_crtc_state *crtc_state,
   struct drm_connector_state *conn_state)
 {
+   struct tc_data *tc = bridge_to_tc(bridge);
+   unsigned int dpi_max_pixrate;
+
/* DSI->DPI interface clock limitation: upto 100 MHz */
if (crtc_state->adjusted_mode.clock > 10)
return -EINVAL;
 
+   bridge_state->hs_rate_min =
+   crtc_state->adjusted_mode.clock *
+   mipi_dsi_pixel_format_to_bpp(tc->dsi->format);
+   /* Split video data transfer across multiple lanes */
+   bridge_state->hs_rate_min /= tc->dsi->lanes;
+   /* DSI bus is DDR */
+   bridge_state->hs_rate_min /= 2;
+   /* Apply 1.2 DSI protocol overhead */
+   bridge_state->hs_rate_min =
+   bridge_state->hs_rate_min * 12 / 10;
+
+   /*
+* The bridge supports maximum DPI resolution 1366x768 24bpp 60Hz
+* and is not capable of running at full 500 MHz in all data lane
+* configurations at least in DSI-to-DPI mode.
+*/
+   dpi_max_pixrate = 1366 * 768 * 24 * 60 / 1000;
+   bridge_state->hs_rate_max =
+   clamp((dpi_max_pixrate * 12 / 10) / tc->dsi->lanes / 2,
+ 0U, 50U);
+
return 0;
 }
 
-- 
2.35.1



[PATCH 5/5] drm/scheduler: deprecate drm_sched_resubmit_jobs

2022-10-26 Thread Christian König
This interface is not working as it should.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/scheduler/sched_main.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index bb28f31bff6f..ecd4afab4adb 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -489,10 +489,21 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, 
bool full_recovery)
 EXPORT_SYMBOL(drm_sched_start);
 
 /**
- * drm_sched_resubmit_jobs - helper to relaunch jobs from the pending list
+ * drm_sched_resubmit_jobs - Deprecated, don't use in new code!
  *
  * @sched: scheduler instance
  *
+ * Re-submitting jobs was a concept AMD came up as cheap way to implement
+ * recovery after a job timeout.
+ *
+ * This turned out to be not working very well. First of all there are many
+ * problem with the dma_fence implementation and requirements. Either the
+ * implementation is risking deadlocks with core memory management or violating
+ * documented implementation details of the dma_fence object.
+ *
+ * Drivers can still save and restore their state for recovery operations, but
+ * we shouldn't make this a general scheduler feature around the dma_fence
+ * interface.
  */
 void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
 {
-- 
2.25.1



[PATCH 2/5] drm/amdgpu: stop resubmitting jobs for bare metal reset

2022-10-26 Thread Christian König
Re-submitting IBs by the kernel has many problems because pre-
requisite state is not automatically re-created as well. In
other words neither binary semaphores nor things like ring
buffer pointers are in the state they should be when the
hardware starts to work on the IBs again.

Additional to that even after more than 5 years of
developing this feature it is still not stable and we have
massively problems getting the reference counts right.

As discussed with user space developers this behavior is not
helpful in the first place. For graphics and multimedia
workloads it makes much more sense to either completely
re-create the context or at least re-submitting the IBs
from userspace.

For compute use cases re-submitting is also not very
helpful since userspace must rely on the accuracy of
the result.

Because of this we stop this practice and instead just
properly note that the fence submission was canceled. The
only use case we keep the re-submission for now is SRIOV
and function level resets.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d4584e577b51..39e94feba1ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5288,7 +5288,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
continue;
 
/* No point to resubmit jobs if we didn't HW reset*/
-   if (!tmp_adev->asic_reset_res && !job_signaled)
+   if (!tmp_adev->asic_reset_res && !job_signaled &&
+   amdgpu_sriov_vf(tmp_adev))
drm_sched_resubmit_jobs(>sched);
 
drm_sched_start(>sched, 
!tmp_adev->asic_reset_res);
-- 
2.25.1



Re: [PATCH v4 4/7] drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection

2022-10-26 Thread Dave Stevenson
On Wed, 26 Oct 2022 at 16:27, Dave Stevenson
 wrote:
>
> On Thu, 20 Oct 2022 at 10:14,  wrote:
> >
> > In order to support higher HDMI frequencies, users have to set the
> > hdmi_enable_4kp60 parameter in their config.txt file.
> >
> > We were detecting this so far by calling clk_round_rate() on the core
> > clock with the frequency we're supposed to run at when one of those
> > modes is enabled. Whether or not the parameter was enabled could then be
> > inferred by the returned rate since the maximum clock rate reported by
> > the firmware was one of the side effect of setting that parameter.
> >
> > However, the recent clock rework we did changed what clk_round_rate()
> > was returning to always return the minimum allowed, and thus this test
> > wasn't reliable anymore.
> >
> > Let's use the new clk_get_max_rate() function to reliably determine the
> > maximum rate allowed on that clock and fix the 4k@60Hz output.
> >
> > Fixes: e9d6cea2af1c ("clk: bcm: rpi: Run some clocks at the minimum rate 
> > allowed")
> > Signed-off-by: Maxime Ripard 
>
> Reviewed-by: Dave Stevenson 
>
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 64f9feabf43e..87961d4de5aa 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -46,6 +46,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -3429,7 +3430,7 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> > device *master, void *data)
> >
> > if (variant->max_pixel_clock == 6) {
> > struct vc4_dev *vc4 = to_vc4_dev(drm);
> > -   long max_rate = clk_round_rate(vc4->hvs->core_clk, 
> > 55000);
> > +   unsigned long max_rate = 
> > rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);

Actually minor nit:
rpi_firmware_clk_get_max_rate returns an unsigned int.
AFAICT we don't need the range of unsigned long in any subsequent
code, so I think it could just be unsigned int here.

clk_round_rate returned a long, and therefore previously it did have to be that.

  Dave

> > if (max_rate < 55000)
> > vc4_hdmi->disable_4kp60 = true;
> >
> > --
> > b4 0.10.1


[PATCH 1/5] drm/amd/amdgpu revert "implement tdr advanced mode"

2022-10-26 Thread Christian König
This reverts commit e6c6338f393b74ac0b303d567bb918b44ae7ad75.

This feature basically re-submits one job after another to
figure out which one was the one causing a hang.

This is obviously incompatible with gang-submit which requires
that multiple jobs run at the same time. It's also absolutely
not helpful to crash the hardware multiple times if a clean
recovery is desired.

For testing and debugging environments we should rather disable
recovery alltogether to be able to inspect the state with a hw
debugger.

Additional to that the sw implementation is clearly buggy and causes
reference count issues for the hardware fence.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 103 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c|   2 +-
 drivers/gpu/drm/scheduler/sched_main.c |  58 ++--
 include/drm/gpu_scheduler.h|   3 -
 4 files changed, 10 insertions(+), 156 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 6f958603c8cc..d4584e577b51 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5070,94 +5070,6 @@ static int amdgpu_device_suspend_display_audio(struct 
amdgpu_device *adev)
return 0;
 }
 
-static void amdgpu_device_recheck_guilty_jobs(
-   struct amdgpu_device *adev, struct list_head *device_list_handle,
-   struct amdgpu_reset_context *reset_context)
-{
-   int i, r = 0;
-
-   for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-   struct amdgpu_ring *ring = adev->rings[i];
-   int ret = 0;
-   struct drm_sched_job *s_job;
-
-   if (!ring || !ring->sched.thread)
-   continue;
-
-   s_job = list_first_entry_or_null(>sched.pending_list,
-   struct drm_sched_job, list);
-   if (s_job == NULL)
-   continue;
-
-   /* clear job's guilty and depend the folowing step to decide 
the real one */
-   drm_sched_reset_karma(s_job);
-   drm_sched_resubmit_jobs_ext(>sched, 1);
-
-   if (!s_job->s_fence->parent) {
-   DRM_WARN("Failed to get a HW fence for job!");
-   continue;
-   }
-
-   ret = dma_fence_wait_timeout(s_job->s_fence->parent, false, 
ring->sched.timeout);
-   if (ret == 0) { /* timeout */
-   DRM_ERROR("Found the real bad job! ring:%s, 
job_id:%llx\n",
-   ring->sched.name, s_job->id);
-
-
-   amdgpu_fence_driver_isr_toggle(adev, true);
-
-   /* Clear this failed job from fence array */
-   amdgpu_fence_driver_clear_job_fences(ring);
-
-   amdgpu_fence_driver_isr_toggle(adev, false);
-
-   /* Since the job won't signal and we go for
-* another resubmit drop this parent pointer
-*/
-   dma_fence_put(s_job->s_fence->parent);
-   s_job->s_fence->parent = NULL;
-
-   /* set guilty */
-   drm_sched_increase_karma(s_job);
-   amdgpu_reset_prepare_hwcontext(adev, reset_context);
-retry:
-   /* do hw reset */
-   if (amdgpu_sriov_vf(adev)) {
-   amdgpu_virt_fini_data_exchange(adev);
-   r = amdgpu_device_reset_sriov(adev, false);
-   if (r)
-   adev->asic_reset_res = r;
-   } else {
-   clear_bit(AMDGPU_SKIP_HW_RESET,
- _context->flags);
-   r = amdgpu_do_asic_reset(device_list_handle,
-reset_context);
-   if (r && r == -EAGAIN)
-   goto retry;
-   }
-
-   /*
-* add reset counter so that the following
-* resubmitted job could flush vmid
-*/
-   atomic_inc(>gpu_reset_counter);
-   continue;
-   }
-
-   /* got the hw fence, signal finished fence */
-   atomic_dec(ring->sched.score);
-   dma_fence_get(_job->s_fence->finished);
-   dma_fence_signal(_job->s_fence->finished);
-   dma_fence_put(_job->s_fence->finished);
-
-   /* remove node from list and free the job */
-   spin_lock(>sched.job_list_lock);
-   list_del_init(_job->list);
-   spin_unlock(>sched.job_list_lock);
-   

[PATCH 1/3] drm: bridge: Add DSI HS clock frequency limits to bridge state

2022-10-26 Thread Marek Vasut
Add the ability to pass DSI HS clock frequency constraints between
neighboring DSI bridges via struct drm_bridge_state . This way the
DSI HS clock frequency negotiation can be implemented instead of
the current ad-hoc method where each bridge attempts to guess the
neighbor HS clock frequency setting or expectation.

Signed-off-by: Marek Vasut 
---
Cc: Laurent Pinchart 
Cc: Lucas Stach 
Cc: Maxime Ripard 
Cc: Robert Foss 
Cc: Sam Ravnborg 
---
 include/drm/drm_atomic.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 10b1990bc1f68..eece7557933d2 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -1117,6 +1117,8 @@ struct drm_bridge_state {
 * @input_bus_cfg: input bus configuration
 */
struct drm_bus_cfg input_bus_cfg;
+   unsigned long hs_rate_min;
+   unsigned long hs_rate_max;
 
/**
 * @output_bus_cfg: input bus configuration
-- 
2.35.1



[PATCH 4/5] drm/scheduler: cleanup define

2022-10-26 Thread Christian König
Remove some not implemented function define

Signed-off-by: Christian König 
---
 include/drm/gpu_scheduler.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index c564be29c5ae..d646ff2fd557 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -492,7 +492,6 @@ void drm_sched_increase_karma(struct drm_sched_job *bad);
 bool drm_sched_dependency_optimized(struct dma_fence* fence,
struct drm_sched_entity *entity);
 void drm_sched_fault(struct drm_gpu_scheduler *sched);
-void drm_sched_job_kickout(struct drm_sched_job *s_job);
 
 void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
 struct drm_sched_entity *entity);
-- 
2.25.1



[PATCH drm-misc-next v4 3/4] drm/arm/hdlcd: plane: use drm managed resources

2022-10-26 Thread Danilo Krummrich
Use drm managed resource allocation (drmm_universal_plane_alloc()) in
order to get rid of the explicit destroy hook in struct drm_plane_funcs.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 2055b1abcec3..1de0f7b23766 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -290,7 +290,6 @@ static const struct drm_plane_helper_funcs 
hdlcd_plane_helper_funcs = {
 static const struct drm_plane_funcs hdlcd_plane_funcs = {
.update_plane   = drm_atomic_helper_update_plane,
.disable_plane  = drm_atomic_helper_disable_plane,
-   .destroy= drm_plane_cleanup,
.reset  = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
@@ -301,21 +300,16 @@ static struct drm_plane *hdlcd_plane_init(struct 
drm_device *drm)
struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct drm_plane *plane = NULL;
u32 formats[ARRAY_SIZE(supported_formats)], i;
-   int ret;
-
-   plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
-   if (!plane)
-   return ERR_PTR(-ENOMEM);
 
for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
formats[i] = supported_formats[i].fourcc;
 
-   ret = drm_universal_plane_init(drm, plane, 0xff, _plane_funcs,
-  formats, ARRAY_SIZE(formats),
-  NULL,
-  DRM_PLANE_TYPE_PRIMARY, NULL);
-   if (ret)
-   return ERR_PTR(ret);
+   plane = drmm_universal_plane_alloc(drm, struct drm_plane, dev, 0xff,
+  _plane_funcs,
+  formats, ARRAY_SIZE(formats),
+  NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+   if (IS_ERR(plane))
+   return plane;
 
drm_plane_helper_add(plane, _plane_helper_funcs);
hdlcd->plane = plane;
-- 
2.37.3



[PATCH drm-misc-next v4 2/4] drm/arm/hdlcd: replace drm->dev_private with drm_to_hdlcd_priv()

2022-10-26 Thread Danilo Krummrich
Using drm_device->dev_private is deprecated. Since we've switched to
devm_drm_dev_alloc(), struct drm_device is now embedded in struct
hdlcd_drm_private, hence we can use container_of() to get the struct
drm_device instance instead.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c |  6 +++---
 drivers/gpu/drm/arm/hdlcd_drv.c  | 10 --
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 +
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 7030339fa232..2055b1abcec3 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -275,7 +275,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane 
*plane,
dest_h = drm_rect_height(_plane_state->dst);
scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
 
-   hdlcd = plane->dev->dev_private;
+   hdlcd = drm_to_hdlcd_priv(plane->dev);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
@@ -298,7 +298,7 @@ static const struct drm_plane_funcs hdlcd_plane_funcs = {
 
 static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
 {
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct drm_plane *plane = NULL;
u32 formats[ARRAY_SIZE(supported_formats)], i;
int ret;
@@ -325,7 +325,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device 
*drm)
 
 int hdlcd_setup_crtc(struct drm_device *drm)
 {
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct drm_plane *primary;
int ret;
 
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 463381d11cff..120c87934a91 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -98,7 +98,7 @@ static void hdlcd_irq_uninstall(struct hdlcd_drm_private 
*hdlcd)
 
 static int hdlcd_load(struct drm_device *drm, unsigned long flags)
 {
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
struct resource *res;
u32 version;
@@ -190,7 +190,7 @@ static int hdlcd_show_underrun_count(struct seq_file *m, 
void *arg)
 {
struct drm_info_node *node = (struct drm_info_node *)m->private;
struct drm_device *drm = node->minor->dev;
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
 
seq_printf(m, "underrun : %d\n", 
atomic_read(>buffer_underrun_count));
seq_printf(m, "dma_end  : %d\n", atomic_read(>dma_end_count));
@@ -203,7 +203,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void 
*arg)
 {
struct drm_info_node *node = (struct drm_info_node *)m->private;
struct drm_device *drm = node->minor->dev;
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
unsigned long clkrate = clk_get_rate(hdlcd->clk);
unsigned long mode_clock = hdlcd->crtc.mode.crtc_clock * 1000;
 
@@ -253,7 +253,6 @@ static int hdlcd_drm_bind(struct device *dev)
 
drm = >base;
 
-   drm->dev_private = hdlcd;
dev_set_drvdata(dev, drm);
 
hdlcd_setup_mode_config(drm);
@@ -324,7 +323,7 @@ static int hdlcd_drm_bind(struct device *dev)
 static void hdlcd_drm_unbind(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
+   struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
 
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
@@ -339,7 +338,6 @@ static void hdlcd_drm_unbind(struct device *dev)
pm_runtime_disable(dev);
of_reserved_mem_device_release(dev);
drm_mode_config_cleanup(drm);
-   drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
 }
 
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index 3892b36767ac..f1c1da2ac2db 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -21,6 +21,7 @@ struct hdlcd_drm_private {
 #endif
 };
 
+#define drm_to_hdlcd_priv(x)   container_of(x, struct hdlcd_drm_private, base)
 #define crtc_to_hdlcd_priv(x)  container_of(x, struct hdlcd_drm_private, crtc)
 
 static inline void hdlcd_write(struct hdlcd_drm_private *hdlcd,
-- 
2.37.3



[PATCH drm-misc-next v4 4/4] drm/arm/hdlcd: remove calls to drm_mode_config_cleanup()

2022-10-26 Thread Danilo Krummrich
drm_mode_config_init() simply calls drmm_mode_config_init(), hence
cleanup is automatically handled through registering
drm_mode_config_cleanup() with drmm_add_action_or_reset().

While at it, get rid of the deprecated drm_mode_config_init() and
replace it with drmm_mode_config_init() directly.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 120c87934a91..49c977cdae40 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -175,14 +175,21 @@ static const struct drm_mode_config_funcs 
hdlcd_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit,
 };
 
-static void hdlcd_setup_mode_config(struct drm_device *drm)
+static int hdlcd_setup_mode_config(struct drm_device *drm)
 {
-   drm_mode_config_init(drm);
+   int ret;
+
+   ret = drmm_mode_config_init(drm);
+   if (ret)
+   return ret;
+
drm->mode_config.min_width = 0;
drm->mode_config.min_height = 0;
drm->mode_config.max_width = HDLCD_MAX_XRES;
drm->mode_config.max_height = HDLCD_MAX_YRES;
drm->mode_config.funcs = _mode_config_funcs;
+
+   return 0;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -255,7 +262,10 @@ static int hdlcd_drm_bind(struct device *dev)
 
dev_set_drvdata(dev, drm);
 
-   hdlcd_setup_mode_config(drm);
+   ret = hdlcd_setup_mode_config(drm);
+   if (ret)
+   goto err_free;
+
ret = hdlcd_load(drm, 0);
if (ret)
goto err_free;
@@ -314,9 +324,7 @@ static int hdlcd_drm_bind(struct device *dev)
hdlcd_irq_uninstall(hdlcd);
of_reserved_mem_device_release(drm->dev);
 err_free:
-   drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
-
return ret;
 }
 
@@ -337,7 +345,6 @@ static void hdlcd_drm_unbind(struct device *dev)
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
of_reserved_mem_device_release(dev);
-   drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
 }
 
-- 
2.37.3



[PATCH drm-misc-next v4 1/4] drm/arm/hdlcd: use drmm_* to allocate driver structures

2022-10-26 Thread Danilo Krummrich
Use drm managed resources to allocate driver structures and get rid of
the deprecated drm_dev_alloc() call and replace it with
devm_drm_dev_alloc().

This also serves as preparation to get rid of drm_device->dev_private
and to fix use-after-free issues on driver unload.

Signed-off-by: Danilo Krummrich 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 12 
 drivers/gpu/drm/arm/hdlcd_drv.h |  1 +
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index a032003c340c..463381d11cff 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -247,13 +247,11 @@ static int hdlcd_drm_bind(struct device *dev)
struct hdlcd_drm_private *hdlcd;
int ret;
 
-   hdlcd = devm_kzalloc(dev, sizeof(*hdlcd), GFP_KERNEL);
-   if (!hdlcd)
-   return -ENOMEM;
+   hdlcd = devm_drm_dev_alloc(dev, _driver, typeof(*hdlcd), base);
+   if (IS_ERR(hdlcd))
+   return PTR_ERR(hdlcd);
 
-   drm = drm_dev_alloc(_driver, dev);
-   if (IS_ERR(drm))
-   return PTR_ERR(drm);
+   drm = >base;
 
drm->dev_private = hdlcd;
dev_set_drvdata(dev, drm);
@@ -319,7 +317,6 @@ static int hdlcd_drm_bind(struct device *dev)
 err_free:
drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
-   drm_dev_put(drm);
 
return ret;
 }
@@ -344,7 +341,6 @@ static void hdlcd_drm_unbind(struct device *dev)
drm_mode_config_cleanup(drm);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
-   drm_dev_put(drm);
 }
 
 static const struct component_master_ops hdlcd_master_ops = {
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index 909c39c28487..3892b36767ac 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -7,6 +7,7 @@
 #define __HDLCD_DRV_H__
 
 struct hdlcd_drm_private {
+   struct drm_device   base;
void __iomem*mmio;
struct clk  *clk;
struct drm_crtc crtc;
-- 
2.37.3



[PATCH drm-misc-next v4 0/4] drm/arm/hdlcd: use drm managed resources

2022-10-26 Thread Danilo Krummrich
Hi,

This patch series converts the driver to use drm managed resources to prevent
potential use-after-free issues on driver unbind/rebind and to get rid of the
usage of deprecated APIs.

Changes in v2:
  - drop patch "drm/arm/hdlcd: crtc: use drmm_crtc_init_with_planes()"

Changes in v3:
  - Fix alternate return paths in srcu read-side critical sections causing a
stall when unregistering the driver.
  - Fix potential null pointer dereference in hdlcd_crtc_cleanup() introduced
dropping the patch in v2.
  - Add a patch to remove explicit calls to drm_mode_config_cleanup().

Changes in v4:
  - Remove patches to protect platform device bound resources with
drm_dev_{enter,exit}, since this would leave the hardware enabled when
regularly unloading the driver e.g. via rmmod.
Instead do this in a later series, once we got drm_dev_unplug() in place
to deal with a regular driver shutdown.

Danilo Krummrich (4):
  drm/arm/hdlcd: use drmm_* to allocate driver structures
  drm/arm/hdlcd: replace drm->dev_private with drm_to_hdlcd_priv()
  drm/arm/hdlcd: plane: use drm managed resources
  drm/arm/hdlcd: remove calls to drm_mode_config_cleanup()

 drivers/gpu/drm/arm/hdlcd_crtc.c | 24 +++
 drivers/gpu/drm/arm/hdlcd_drv.c  | 41 
 drivers/gpu/drm/arm/hdlcd_drv.h  |  2 ++
 3 files changed, 32 insertions(+), 35 deletions(-)


base-commit: e1e7bc481d49c3e3ada11029ce0d9b85a0a539d7
-- 
2.37.3



[PATCH v6 22/23] drm/vc4: vec: Add support for more analog TV standards

2022-10-26 Thread maxime
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.

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

---
Changes in v6:
- Support PAL60 again
---
 drivers/gpu/drm/vc4/vc4_vec.c | 111 --
 1 file changed, 107 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 1dda451c8def..d82aef168075 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
 
@@ -197,10 +227,15 @@ enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_NTSC_J,
VC4_VEC_TV_MODE_PAL,
VC4_VEC_TV_MODE_PAL_M,
+   VC4_VEC_TV_MODE_NTSC_443,
+   VC4_VEC_TV_MODE_PAL_60,
+   VC4_VEC_TV_MODE_PAL_N,
+   VC4_VEC_TV_MODE_SECAM,
 };
 
 struct vc4_vec_tv_mode {
unsigned int mode;
+   u16 expected_htotal;
u32 config0;
u32 config1;
u32 custom_freq;
@@ -236,35 +271,68 @@ static const struct debugfs_reg32 vec_regs[] = {
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
{
.mode = DRM_MODE_TV_MODE_NTSC,
+   .expected_htotal = 858,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC_443,
+   .expected_htotal = 858,
+   .config0 = VEC_CONFIG0_NTSC_STD,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+   .custom_freq = 0x2a098acb,
+   },
{
.mode = DRM_MODE_TV_MODE_NTSC_J,
+   .expected_htotal = 858,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
{
.mode = DRM_MODE_TV_MODE_PAL,
+   .expected_htotal = 864,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+   {
+   /* PAL-60 */
+   

[PATCH v6 09/23] drm/modes: Switch to named mode descriptors

2022-10-26 Thread maxime
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 
---
 drivers/gpu/drm/drm_modes.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 37542612912b..7594b657f86a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2224,9 +2224,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,
@@ -2258,14 +2262,15 @@ static int drm_mode_parse_cmdline_named_mode(const char 
*name,
 * We're sure we're a named mode at this 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 = _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.11.0-dev-99e3a


[PATCH v6 23/23] drm/sun4i: tv: Convert to the new TV mode property

2022-10-26 Thread maxime
Now that the core can deal fine with analog TV modes, let's convert the
sun4i TV driver to leverage those new features.

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

---
Changes in v6:
- Convert to new get_modes helper

Changes in v5:
- Removed the count variable in get_modes
- Removed spurious vc4 change
---
 drivers/gpu/drm/sun4i/sun4i_tv.c | 141 ++-
 1 file changed, 34 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index c65f0a89b6b0..9625a00a48ba 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -141,23 +141,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;
@@ -213,7 +204,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,
.mode   = SUN4I_TVE_CFG0_RES_480i,
.chroma_freq= 0x21f07c1f,
.yc_en  = true,
@@ -222,17 +213,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,
 
@@ -242,23 +222,12 @@ static const struct tv_mode tv_modes[] = {
.resync_params  = _resync_parameters,
},
{
-   .name   = "PAL",
+   .tv_mode= DRM_MODE_TV_MODE_PAL,
.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,
 
@@ -276,63 +245,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 = _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 = _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;
-   

[PATCH v6 20/23] drm/vc4: vec: Check for VEC output constraints

2022-10-26 Thread maxime
From: Mateusz Kwiatkowski 

The VEC can accept pretty much any relatively reasonable mode, but still
has a bunch of constraints to meet.

Let's create an atomic_check() implementation that will make sure we
don't end up accepting a non-functional mode.

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

---

Changes in v6:
- Used htotal instead of vtotal to discriminate PAL against NTSC
---
 drivers/gpu/drm/vc4/vc4_vec.c | 50 +++
 1 file changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 90e375a8a8f9..bfa8a58dba30 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -453,6 +453,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
 {
+   const struct drm_display_mode *mode = _state->adjusted_mode;
const struct vc4_vec_tv_mode *vec_mode;
 
vec_mode = _vec_tv_modes[conn_state->tv.legacy_mode];
@@ -461,6 +462,55 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
!drm_mode_equal(vec_mode->mode, _state->adjusted_mode))
return -EINVAL;
 
+   if (mode->crtc_hdisplay % 4)
+   return -EINVAL;
+
+   if (!(mode->crtc_hsync_end - mode->crtc_hsync_start))
+   return -EINVAL;
+
+   switch (mode->htotal) {
+   /* NTSC */
+   case 858:
+   if (mode->crtc_vtotal > 262)
+   return -EINVAL;
+
+   if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 253)
+   return -EINVAL;
+
+   if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+   return -EINVAL;
+
+   if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+   return -EINVAL;
+
+   if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 4)
+   return -EINVAL;
+
+   break;
+
+   /* PAL/SECAM */
+   case 864:
+   if (mode->crtc_vtotal > 312)
+   return -EINVAL;
+
+   if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 305)
+   return -EINVAL;
+
+   if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+   return -EINVAL;
+
+   if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+   return -EINVAL;
+
+   if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 2)
+   return -EINVAL;
+
+   break;
+
+   default:
+   return -EINVAL;
+   }
+
return 0;
 }
 

-- 
b4 0.11.0-dev-99e3a


[PATCH v6 19/23] drm/vc4: vec: Use TV Reset implementation

2022-10-26 Thread maxime
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().

Reviewed-by: Noralf Trønnes 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_vec.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index adc9bf99e3fd..90e375a8a8f9 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -268,6 +268,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;
@@ -288,7 +294,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.11.0-dev-99e3a


[PATCH v6 21/23] drm/vc4: vec: Convert to the new TV mode property

2022-10-26 Thread maxime
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. We're also making use of
the new analog TV atomic_check helper to make sure we trigger a modeset
whenever the TV mode is updated.

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

---
Changes in v6:
- Use new get_modes helper

Changes in v5:
- Renamed tv_mode_names into legacy_tv_mode_names

Changes in v4:
- Removed the count variable in .get_modes
---
 drivers/gpu/drm/vc4/vc4_vec.c | 185 +-
 1 file changed, 129 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index bfa8a58dba30..1dda451c8def 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;
@@ -225,43 +233,51 @@ 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 = _mode,
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_NTSC_J] = {
-   .mode = _mode,
+   {
+   .mode = DRM_MODE_TV_MODE_NTSC_J,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_PAL] = {
-   .mode = _mode,
+   {
+   .mode = DRM_MODE_TV_MODE_PAL,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
-   [VC4_VEC_TV_MODE_PAL_M] = {
-   .mode = _mode,
+   {
+   .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 = _vec_tv_modes[i];
+
+   if (tv_mode->mode == mode)
+   return tv_mode;
+   }
+
+   return NULL;
+}
+
+static const struct drm_prop_enum_list legacy_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)
 {
@@ -274,21 +290,74 @@ static void vc4_vec_connector_reset(struct drm_connector 
*connector)
drm_atomic_helper_connector_tv_reset(connector);
 }
 
-static int vc4_vec_connector_get_modes(struct drm_connector *connector)
+static int
+vc4_vec_connector_set_property(struct drm_connector *connector,
+  struct drm_connector_state *state,
+  struct drm_property *property,
+  uint64_t val)
 {
-   struct drm_connector_state *state = connector->state;
-   struct drm_display_mode *mode;
-
-   mode = drm_mode_duplicate(connector->dev,
- vc4_vec_tv_modes[state->tv.legacy_mode].mode);
-   if (!mode) {
-   DRM_ERROR("Failed to create a new display mode\n");
-   return -ENOMEM;
+   struct 

[PATCH v6 12/23] drm/connector: Add a function to lookup a TV mode by its name

2022-10-26 Thread maxime
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.

Reviewed-by: Noralf Trønnes 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_connector.c | 24 
 include/drm/drm_connector.h |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 820f4c730b38..30611c616435 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -991,6 +991,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 = 
_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 5c5e67de2296..276f5cb0f351 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1864,6 +1864,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.11.0-dev-99e3a


[PATCH v6 17/23] drm/atomic-helper: Add a TV properties reset helper

2022-10-26 Thread maxime
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.

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

---
Changes in v6:
- Use tv_mode_specified instead of a !0 tv_mode to set the default
---
 drivers/gpu/drm/drm_atomic_state_helper.c | 75 +++
 include/drm/drm_atomic_state_helper.h |  1 +
 2 files changed, 76 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index dfb57217253b..e1fc3f26340a 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 = >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(>base,
+  prop, ))
+   state->tv.mode = val;
+
+   if (cmdline->tv_mode_specified)
+   state->tv.mode = cmdline->tv_mode;
+
+   prop = dev->mode_config.tv_select_subconnector_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.select_subconnector = val;
+
+   prop = dev->mode_config.tv_subconnector_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.subconnector = val;
+
+   prop = dev->mode_config.tv_brightness_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.brightness = val;
+
+   prop = dev->mode_config.tv_contrast_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.contrast = val;
+
+   prop = dev->mode_config.tv_flicker_reduction_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.flicker_reduction = val;
+
+   prop = dev->mode_config.tv_overscan_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.overscan = val;
+
+   prop = dev->mode_config.tv_saturation_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   state->tv.saturation = val;
+
+   prop = dev->mode_config.tv_hue_property;
+   if (prop)
+   if (!drm_object_property_get_default_value(>base,
+  prop, ))
+   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 

[PATCH v6 16/23] drm/probe-helper: Provide a TV get_modes helper

2022-10-26 Thread maxime
Most of the TV connectors will need a similar get_modes implementation
that will, depending on the drivers' capabilities, register the 480i and
576i modes.

That implementation will also need to set the preferred flag and order
the modes based on the driver and users preferrence.

This is especially important to guarantee that a userspace stack such as
Xorg can start and pick up the preferred mode while maintaining a
working output.

Signed-off-by: Maxime Ripard 

---
Changes in v6:
- New patch
---
 drivers/gpu/drm/drm_probe_helper.c | 97 ++
 include/drm/drm_probe_helper.h |  1 +
 2 files changed, 98 insertions(+)

diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index 69b0b2b9cc1c..4a60575f5c66 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -1147,3 +1147,100 @@ int drm_connector_helper_get_modes(struct drm_connector 
*connector)
return count;
 }
 EXPORT_SYMBOL(drm_connector_helper_get_modes);
+
+static bool tv_mode_supported(struct drm_connector *connector,
+ enum drm_connector_tv_mode mode)
+{
+   struct drm_device *dev = connector->dev;
+   struct drm_property *property = dev->mode_config.tv_mode_property;
+
+   unsigned int i;
+
+   for (i = 0; i < property->num_values; i++)
+   if (property->values[i] == mode)
+   return true;
+
+   return false;
+}
+
+/**
+ * drm_connector_helper_tv_get_modes - Fills the modes availables to a TV 
connector
+ * @connector: The connector
+ *
+ * Fills the available modes for a TV connector based on the supported
+ * TV modes, and the default mode expressed by the kernel command line.
+ *
+ * This can be used as the default TV connector helper .get_modes() hook
+ * if the driver does not need any special processing.
+ *
+ * Returns:
+ * The number of modes added to the connector.
+ */
+int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
+{
+   struct drm_device *dev = connector->dev;
+   struct drm_cmdline_mode *cmdline = >cmdline_mode;
+   struct drm_display_mode *tv_modes[2] = {};
+   struct drm_display_mode *mode;
+   unsigned int first_mode_idx;
+   unsigned int count = 0;
+   uint64_t default_mode;
+   int ret;
+
+   if (!dev->mode_config.tv_mode_property)
+   return 0;
+
+   if (tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC) ||
+   tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC_443) ||
+   tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC_J) ||
+   tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL_M)) {
+   mode = drm_mode_analog_ntsc_480i(connector->dev);
+   if (!mode)
+   return 0;
+
+   tv_modes[count++] = mode;
+   }
+
+   if (tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL) ||
+   tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL_N) ||
+   tv_mode_supported(connector, DRM_MODE_TV_MODE_SECAM)) {
+   mode = drm_mode_analog_pal_576i(connector->dev);
+   if (!mode)
+   return 0;
+
+   tv_modes[count++] = mode;
+   }
+
+   if (count == 1) {
+   mode->type |= DRM_MODE_TYPE_PREFERRED;
+   drm_mode_probed_add(connector, mode);
+   return count;
+   }
+
+   ret = drm_object_property_get_default_value(>base,
+   
dev->mode_config.tv_mode_property,
+   _mode);
+   if (ret)
+   return 0;
+
+   if (cmdline->tv_mode_specified)
+   default_mode = cmdline->tv_mode;
+
+   if ((default_mode == DRM_MODE_TV_MODE_NTSC) ||
+   (default_mode == DRM_MODE_TV_MODE_NTSC_443) ||
+   (default_mode == DRM_MODE_TV_MODE_NTSC_J) ||
+   (default_mode == DRM_MODE_TV_MODE_PAL_M))
+   first_mode_idx = 0;
+   else
+   first_mode_idx = 1;
+
+   mode = tv_modes[first_mode_idx];
+   mode->type |= DRM_MODE_TYPE_PREFERRED;
+   drm_mode_probed_add(connector, mode);
+
+   mode = first_mode_idx ? tv_modes[0] : tv_modes[1];
+   drm_mode_probed_add(connector, mode);
+
+   return count;
+}
+EXPORT_SYMBOL(drm_connector_helper_tv_get_modes);
diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h
index 5880daa14624..4977e0ab72db 100644
--- a/include/drm/drm_probe_helper.h
+++ b/include/drm/drm_probe_helper.h
@@ -35,5 +35,6 @@ int drm_connector_helper_get_modes_from_ddc(struct 
drm_connector *connector);
 int drm_connector_helper_get_modes_fixed(struct drm_connector *connector,
 const struct drm_display_mode 
*fixed_mode);
 int drm_connector_helper_get_modes(struct drm_connector *connector);
+int drm_connector_helper_tv_get_modes(struct 

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

2022-10-26 Thread maxime
The analog TV connector drivers share some atomic_check logic, and the new
TV standard property have created some boilerplate that can be be shared
across drivers too.

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

Reviewed-by: Noralf Trønnes 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_atomic_state_helper.c | 49 +++
 include/drm/drm_atomic_state_helper.h |  3 ++
 2 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index e1fc3f26340a..3a467013c656 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -556,6 +556,55 @@ 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;
+
+   if ((old_conn_state->tv.margins.left != 
new_conn_state->tv.margins.left) ||
+   (old_conn_state->tv.margins.right != 
new_conn_state->tv.margins.right) ||
+   (old_conn_state->tv.margins.top != new_conn_state->tv.margins.top) 
||
+   (old_conn_state->tv.margins.bottom != 
new_conn_state->tv.margins.bottom) ||
+   (old_conn_state->tv.mode != new_conn_state->tv.mode) ||
+   (old_conn_state->tv.brightness != new_conn_state->tv.brightness) ||
+   (old_conn_state->tv.contrast != new_conn_state->tv.contrast) ||
+   (old_conn_state->tv.flicker_reduction != 
new_conn_state->tv.flicker_reduction) ||
+   (old_conn_state->tv.overscan != new_conn_state->tv.overscan) ||
+   (old_conn_state->tv.saturation != new_conn_state->tv.saturation) ||
+   (old_conn_state->tv.hue != new_conn_state->tv.hue))
+   crtc_state->connectors_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.11.0-dev-99e3a


[PATCH v6 13/23] drm/modes: Introduce the tv_mode property as a command-line option

2022-10-26 Thread maxime
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 

---
Changes in v6:
- Add a tv_mode_specified field

Changes in v4:
- Add Documentation of the command-line option to modedb.rst
---
 Documentation/fb/modedb.rst |  2 +
 drivers/gpu/drm/drm_modes.c | 37 --
 drivers/gpu/drm/tests/drm_cmdline_parser_test.c | 67 +
 include/drm/drm_connector.h | 12 +
 4 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst
index 4d2411e32ebb..5d6361a77f3c 100644
--- a/Documentation/fb/modedb.rst
+++ b/Documentation/fb/modedb.rst
@@ -65,6 +65,8 @@ Valid options are::
   - reflect_y (boolean): Perform an axial symmetry on the Y axis
   - rotate (integer): Rotate the initial framebuffer by x
 degrees. Valid values are 0, 90, 180 and 270.
+  - tv_mode: Analog TV mode. One of "NTSC", "NTSC-443", "NTSC-J", "PAL",
+"PAL-M", "PAL-N", or "SECAM".
   - panel_orientation, one of "normal", "upside_down", "left_side_up", or
 "right_side_up". For KMS drivers only, this sets the "panel orientation"
 property on the kms connector as hint for kms users.
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index c826f9583a1d..dc037f7ceb37 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2133,6 +2133,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;
+   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_specified = true;
+   mode->tv_mode = ret;
+
+   return 0;
+}
+
 static int drm_mode_parse_cmdline_options(const char *str,
  bool freestanding,
  const struct drm_connector *connector,
@@ -2202,6 +2226,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;
}
@@ -2230,20 +2257,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),
+   NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, 
DRM_MODE_TV_MODE_PAL),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2288,6 +2317,8 @@ 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->tv_mode_specified = true;
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 34790e7a3760..3e711b83b823 100644
--- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
+++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
@@ -927,6 +927,14 @@ 

[PATCH v6 15/23] drm/modes: Introduce more named modes

2022-10-26 Thread maxime
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 

---
Changes in v6:
- Renamed the tests to follow DRM test naming convention

Changes in v5:
- Switched to KUNIT_ASSERT_NOT_NULL
---
 drivers/gpu/drm/drm_modes.c |  2 +
 drivers/gpu/drm/tests/drm_client_modeset_test.c | 54 +
 2 files changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 85aa9898c229..530516a166bc 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2272,7 +2272,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),
+   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),
+   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 fdfe9e20702e..b3820d25beca 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -133,6 +133,32 @@ static void drm_test_pick_cmdline_named_ntsc(struct kunit 
*test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
 }
 
+static void drm_test_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 = >connector;
+   struct drm_cmdline_mode *cmdline_mode = >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(>mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(>mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
+}
+
 static void drm_test_pick_cmdline_named_pal(struct kunit *test)
 {
struct drm_client_modeset_test_priv *priv = test->priv;
@@ -159,10 +185,38 @@ static void drm_test_pick_cmdline_named_pal(struct kunit 
*test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_pal_576i(drm), 
mode));
 }
 
+static void drm_test_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 = >connector;
+   struct drm_cmdline_mode *cmdline_mode = >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(>mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(>mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), 
mode));
+}
+
 static struct kunit_case drm_test_pick_cmdline_tests[] = {
KUNIT_CASE(drm_test_pick_cmdline_res_1920_1080_60),
KUNIT_CASE(drm_test_pick_cmdline_named_ntsc),
+   KUNIT_CASE(drm_test_pick_cmdline_named_ntsc_j),
KUNIT_CASE(drm_test_pick_cmdline_named_pal),
+   KUNIT_CASE(drm_test_pick_cmdline_named_pal_m),
{}
 };
 

-- 
b4 0.11.0-dev-99e3a


[PATCH v6 10/23] drm/modes: Fill drm_cmdline mode from named modes

2022-10-26 Thread maxime
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 
---
 drivers/gpu/drm/drm_modes.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 7594b657f86a..acee23e1a8b7 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2226,11 +2226,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,
@@ -2271,6 +2282,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.11.0-dev-99e3a


[PATCH v6 14/23] drm/modes: Properly generate a drm_display_mode from a named mode

2022-10-26 Thread maxime
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 

---
Changes in v6:
- Fix get_modes to return 0 instead of an error code
- Rename the tests to follow the DRM test naming convention

Changes in v5:
- Switched to KUNIT_ASSERT_NOT_NULL
---
 drivers/gpu/drm/drm_modes.c | 34 ++-
 drivers/gpu/drm/tests/drm_client_modeset_test.c | 77 -
 2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index dc037f7ceb37..85aa9898c229 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2497,6 +2497,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 = _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
@@ -2514,7 +2544,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 3aa1acfe75df..fdfe9e20702e 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -21,7 +21,26 @@ struct drm_client_modeset_test_priv {
 
 static int drm_client_modeset_connector_get_modes(struct drm_connector 
*connector)
 {
-   return drm_add_modes_noedid(connector, 1920, 1200);
+   struct drm_display_mode *mode;
+   int count;
+
+   count = drm_add_modes_noedid(connector, 1920, 1200);
+
+   mode = drm_mode_analog_ntsc_480i(connector->dev);
+   if (!mode)
+   return count;
+
+   drm_mode_probed_add(connector, mode);
+   count += 1;
+
+   mode = drm_mode_analog_pal_576i(connector->dev);
+   if (!mode)
+   return count;
+
+   drm_mode_probed_add(connector, mode);
+   count += 1;
+
+   return count;
 }
 
 static const struct drm_connector_helper_funcs 
drm_client_modeset_connector_helper_funcs = {
@@ -52,6 +71,9 @@ static int drm_client_modeset_test_init(struct kunit *test)
 
drm_connector_helper_add(>connector, 
_client_modeset_connector_helper_funcs);
 
+   priv->connector.interlace_allowed = true;
+   priv->connector.doublescan_allowed = true;
+
return 0;
 
 }
@@ -85,9 +107,62 @@ static void drm_test_pick_cmdline_res_1920_1080_60(struct 
kunit *test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
 }
 
+static void drm_test_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 = >connector;
+   struct drm_cmdline_mode *cmdline_mode = >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,
+   

[PATCH v6 07/23] drm/client: Add some tests for drm_connector_pick_cmdline_mode()

2022-10-26 Thread maxime
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.

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

---
Changes in v6:
- Rename tests to be consistent with DRM tests naming convention

Changes in v5:
- Removed useless (for now) count and modes intermediate variables in
  get_modes
- Switched to kunit assertions in test init, and to KUNIT_ASSERT_NOT_NULL
  instead of KUNIT_ASSERT_PTR_NE(..., NULL)

Changes in v4:
- Removed MODULE macros
---
 drivers/gpu/drm/drm_client_modeset.c|   4 +
 drivers/gpu/drm/tests/drm_client_modeset_test.c | 100 
 2 files changed, 104 insertions(+)

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 ..3aa1acfe75df
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -0,0 +1,100 @@
+// 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)
+{
+   return drm_add_modes_noedid(connector, 1920, 1200);
+}
+
+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);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   test->priv = priv;
+
+   priv->drm = drm_kunit_device_init(test, "drm-client-modeset-test");
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
+
+   ret = drmm_connector_init(priv->drm, >connector,
+ _client_modeset_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown,
+ NULL);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   drm_connector_helper_add(>connector, 
_client_modeset_connector_helper_funcs);
+
+   return 0;
+
+}
+
+static void drm_test_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 = >connector;
+   struct drm_cmdline_mode *cmdline_mode = >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_NOT_NULL(test, expected_mode);
+
+   KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+   connector,
+   
cmdline_mode));
+
+   mutex_lock(>mode_config.mutex);
+   ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+   mutex_unlock(>mode_config.mutex);
+   KUNIT_ASSERT_GT(test, ret, 0);
+
+   mode = drm_connector_pick_cmdline_mode(connector);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
+}
+
+
+static struct kunit_case drm_test_pick_cmdline_tests[] = {
+   KUNIT_CASE(drm_test_pick_cmdline_res_1920_1080_60),
+   {}
+};
+
+static struct kunit_suite drm_test_pick_cmdline_test_suite = {
+   .name = "drm_test_pick_cmdline",
+   .init = drm_client_modeset_test_init,
+   .test_cases = drm_test_pick_cmdline_tests
+};
+
+kunit_test_suite(drm_test_pick_cmdline_test_suite);

-- 
b4 0.11.0-dev-99e3a


[PATCH v6 11/23] drm/connector: Add pixel clock to cmdline mode

2022-10-26 Thread maxime
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 
---
 drivers/gpu/drm/drm_modes.c | 9 ++---
 include/drm/drm_connector.h | 7 +++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index acee23e1a8b7..c826f9583a1d 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2226,22 +2226,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,
@@ -2282,6 +2284,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 96b2e4e12334..5c5e67de2296 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1273,6 +1273,13 @@ struct drm_cmdline_mode {
 */
bool bpp_specified;
 
+   /**
+* @pixel_clock:
+*
+* Pixel Clock in kHz. Optional.
+*/
+   unsigned int pixel_clock;
+
/**
 * @xres:
 *

-- 
b4 0.11.0-dev-99e3a


[PATCH v6 08/23] drm/modes: Move named modes parsing to a separate function

2022-10-26 Thread maxime
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.

In order for the tests to still pass, some extra checks are needed, so
it's not a 1:1 move.

Signed-off-by: Maxime Ripard 

---
Changes in v6:
- Simplify the test for connection status extras
- Simplify the code path to call drm_mode_parse_cmdline_named_mode

Changes in v4:
- Fold down all the named mode patches that were split into a single
  patch again to maintain bisectability
---
 drivers/gpu/drm/drm_modes.c | 70 +
 1 file changed, 58 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 71c050c3ee6b..37542612912b 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2229,6 +2229,51 @@ 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 (name_end == 1 &&
+   (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
+   return 0;
+
+   /*
+* We're sure we're a named mode at this 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
@@ -2265,7 +2310,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;
@@ -2306,18 +2351,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 */
+   if (!mode_end)
+   return false;
 
-   strcpy(mode->name, drm_named_modes_whitelist[i]);
-   mode->specified = true;
-   break;
-   }
-   }
+   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 */
if (!mode->specified && isdigit(name[0])) {

-- 
b4 0.11.0-dev-99e3a


[PATCH v6 06/23] drm/modes: Add a function to generate analog display modes

2022-10-26 Thread maxime
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 

---
Changes in v6:
- Fix typo

Changes in v4:
- Reworded the line length check comment
- Switch to HZ_PER_KHZ in tests
- Use previous timing to fill our mode
- Move the number of lines check earlier
---
 drivers/gpu/drm/drm_modes.c| 474 +
 drivers/gpu/drm/tests/Makefile |   1 +
 drivers/gpu/drm/tests/drm_modes_test.c | 144 ++
 include/drm/drm_modes.h|  17 ++
 4 files changed, 636 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5d4ac79381c4..71c050c3ee6b 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -116,6 +116,480 @@ void drm_mode_probed_add(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_probed_add);
 
+enum drm_mode_analog {
+   DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
+   DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
+};
+
+/*
+ * 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)
+
+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;
+
+   unsigned intbt601_hfp;
+
+   

[PATCH v6 05/23] drm/connector: Add TV standard property

2022-10-26 Thread maxime
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 enum 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, and the property
creation function will filter out the modes not supported.

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

Signed-off-by: Maxime Ripard 

---
Changes in v5:
- Create an analog TV properties documentation section, and document TV
  Mode there instead of the csv file

Changes in v4:
- Add property documentation to kms-properties.csv
- Fix documentation
---
 Documentation/gpu/drm-kms.rst |   6 ++
 drivers/gpu/drm/drm_atomic_uapi.c |   4 ++
 drivers/gpu/drm/drm_connector.c   | 122 +-
 include/drm/drm_connector.h   |  64 
 include/drm/drm_mode_config.h |   8 +++
 5 files changed, 203 insertions(+), 1 deletion(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index b4377a545425..321f2f582c64 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -520,6 +520,12 @@ HDMI Specific Connector Properties
 .. kernel-doc:: drivers/gpu/drm/drm_connector.c
:doc: HDMI connector properties
 
+Analog TV Specific Connector Properties
+--
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+   :doc: Analog TV Connector Properties
+
 Standard CRTC Properties
 
 
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..820f4c730b38 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -980,6 +980,17 @@ 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, "NTSC" },
+   { DRM_MODE_TV_MODE_NTSC_443, "NTSC-443" },
+   { DRM_MODE_TV_MODE_NTSC_J, "NTSC-J" },
+   { DRM_MODE_TV_MODE_PAL, "PAL" },
+   { DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
+   { DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
+   { DRM_MODE_TV_MODE_SECAM, "SECAM" },
+};
+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 */
@@ -1548,6 +1559,71 @@ 
EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
  * infoframe values is done through drm_hdmi_avi_infoframe_content_type().
  */
 
+/*
+ * TODO: Document the properties:
+ *   - left margin
+ *   - right margin
+ *   - top margin
+ *   - bottom margin
+ *   - brightness
+ *   - contrast
+ *   - flicker reduction
+ *   - hue
+ *   - mode
+ *   - overscan
+ *   - saturation
+ *   - select subconnector
+ *   - subconnector
+ */
+/**
+ * DOC: Analog TV Connector Properties
+ *
+ * TV Mode:
+ * Indicates the TV Mode used on an analog TV connector. The value
+ * of this property can be one of the following:
+ *
+ * NTSC:
+ * TV Mode is CCIR System M (aka 525-lines) together with
+ * the NTSC Color Encoding.
+ *
+ * NTSC-443:
+ *
+ * TV Mode is CCIR System M (aka 525-lines) together with
+ *

[PATCH v6 04/23] drm/connector: Rename drm_mode_create_tv_properties

2022-10-26 Thread maxime
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.

Reviewed-by: Lyude Paul  # nouveau
Reviewed-by: Noralf Trønnes 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_connector.c   | 12 ++--
 drivers/gpu/drm/gud/gud_connector.c   |  4 ++--
 drivers/gpu/drm/i2c/ch7006_drv.c  |  2 +-
 drivers/gpu/drm/i915/display/intel_tv.c   |  2 +-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c |  2 +-
 drivers/gpu/drm/vc4/vc4_vec.c |  5 +++--
 include/drm/drm_connector.h   |  6 +++---
 7 files changed, 17 insertions(+), 16 deletions(-)

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 86e992b2108b..034e78360d4f 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] = [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 ef69f9bdeace..b63bad04b09d 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 = >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 b2f42bf929e2..748821ebdf65 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1995,7 +1995,7 @@ 

[PATCH v6 03/23] drm/connector: Only register TV mode property if present

2022-10-26 Thread maxime
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.

Acked-by: Noralf Trønnes 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_connector.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

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.11.0-dev-99e3a


[PATCH v6 00/23] drm: Analog TV Improvements

2022-10-26 Thread maxime
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 mode 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 mode':1 # NTSC
modetest -M vc4  -s 53:720x576i -w 53:'TV mode':4 # PAL

Let me know what you think,
Maxime

To: David Airlie 
To: Daniel Vetter 
To: Maarten Lankhorst 
To: Maxime Ripard 
To: Thomas Zimmermann 
To: Emma Anholt 
To: Jani Nikula 
To: Joonas Lahtinen 
To: Rodrigo Vivi 
To: Tvrtko Ursulin 
To: Ben Skeggs 
To: Karol Herbst 
To: Lyude Paul 
To: Chen-Yu Tsai 
To: Jernej Skrabec 
To: Samuel Holland 
Cc: Geert Uytterhoeven 
Cc: Mateusz Kwiatkowski 
Cc: "Noralf Trønnes" 
Cc: Dave Stevenson 
Cc: Dom Cobley 
Cc: Phil Elwell 
Cc: 
Cc: linux-ker...@vger.kernel.org
Cc: intel-...@lists.freedesktop.org
Cc: nouv...@lists.freedesktop.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-su...@lists.linux.dev
Cc: Hans de Goede 
Signed-off-by: Maxime Ripard 

---
Changes in v6:
- Add and convert to a new get_modes helper to create the PAL and NTSC modes in
  the proper order, with the right preferred mode flag, depending on the driver
  capabilities and defaults.
- Support PAL60
- Renamed tests to be consistent with DRM tests naming convention
- Simplified a bit the named mode parsing code
- Add a tv_mode_specified field
- Return 0 in get_modes implementations instead of error codes
- Link to v5: 
https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v5-0-d841cc64f...@cerno.tech

Changes in v5:
- Dropped TV Standard documentation removal
- Switched the TV Mode documentation from CSV to actual documentation
- Switched to kunit assertions where possible
- Switched to KUNIT_ASSERT_NOT_NULL instead of KUNIT_ASSERT_PTR_NE(..., NULL)
- Shuffled a bit the introduction of drm_client_modeset_connector_get_modes 
between patches
- Renamed tv_mode_names to legacy_tv_mode_names
- Removed the count variable in sun4i_tv_comp_get_modes
- Rebased on top of current drm-misc-next
- Link to v4: 
https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v4-0-60d38873f...@cerno.tech

Changes in v4:
- Removed the unused TV Standard property documentation
- Added the TV Mode property documentation to kms-properties.csv
- Fixed the documentation of drm_mode_create_tv_properties()
- Removed DRM_MODE_TV_MODE_NONE
- Reworded the line length check comment in drm_mode_analog_tv tests
- Switched to HZ_PER_KHZ in drm_mode_analog_tv tests
- Reworked drm_mode_analog_tv to fill our mode using the previously computed
  timings
- Added the command-line option documentation to modedb.rst
- Improved the Kunit helpers cleanup
- Moved the subconnector documentation renaming to the proper patch
- Added the various review tags
- Removed the count variable in vc4_vec_connector_get_modes
- Rebased on drm-misc-next-2022-09-23 and fixed a merge conflict
- Folded all the named mode parsing improvements in a single patch
- Link to v3: 
https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v2-0-f733a0ed9...@cerno.tech

Changes in v3:
- Applied some of the fixes to vc4 and sun4i
- 

  1   2   >