Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp3603449pxj; Tue, 1 Jun 2021 08:58:28 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxGRU0VARI+TWoIewNxmxVo/CzNQtOaf88LJ/1eO1qFLpruCx3uyMrfvt4gGLMmt2W9f6pT X-Received: by 2002:aa7:ce05:: with SMTP id d5mr9798465edv.325.1622563108225; Tue, 01 Jun 2021 08:58:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622563108; cv=none; d=google.com; s=arc-20160816; b=fEB8830X8r7QNak3ovz0eFMA986b4yhgX0qrGOEn1aGtIzl1hkO9dgiix7BZuoS4In rGMkAlc1fDZMV3WlpsEBZz0XqbABEc3BCgRf1Y3/tBUGn/xReG+bkLwrQYwU9O8ByxY2 F7x5KQUP1gGnwnXSVD5vWAgZSAzb1VrZBq8FyiAauNwKsG8gqMdtFDg1jXzfcMaZef8I joKxxvE5Fgz6IumyIVSnwrXSUy9p9h6CYkJlFIiiO2Q2H7Yh4HbOSzkA8lOi2KLr1o5q CrGcickb/FgSQUwZZrsJKerdBkLgDiqqUVUyMItcLLG5GNgxw3c+WeQtNB53SdbZrf3T 58VQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:mail-followup-to:message-id:subject:cc:to:from:date :dkim-signature; bh=WqUgAHrpDOUpUOXO/CHtnZe/20C1L3Tz7SUmh5uKdic=; b=op02SVX5k2muM/zo3pOizenp5JdMygejoNSSk5V1z10yDnm7XaL8T4jSJav0ZxIkih 8cqmdaXAaG0uaK+/RrJiqZ02AVot2OaUarqUdyYhGSxzlVnxgnpyiqQAp5L7GkGjmqOW 1YV2V5il/cBdPxi4RUhDnhSsFCymLBgrfuonyN6i3mB2Z1bYxZwK22sMP2BGyZbAyF7v HjInboqq4hn36gA1CHAQuXuQ8UTeHLuHR6VuL5lT+ChiwKM2Qk2kQO72petn93OFfEHy ED4Ktro0rJRfuBZ1+0s2j4c65fU4w/NSn0Hs3hCUevCrgjyzrkvLJnhJ1YMKtkhQPF+4 HPPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ffwll.ch header.s=google header.b=SxNumUnP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z11si12254846edq.40.2021.06.01.08.58.05; Tue, 01 Jun 2021 08:58:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@ffwll.ch header.s=google header.b=SxNumUnP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233301AbhFAPzw (ORCPT + 99 others); Tue, 1 Jun 2021 11:55:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230523AbhFAPzu (ORCPT ); Tue, 1 Jun 2021 11:55:50 -0400 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53DE4C06174A for ; Tue, 1 Jun 2021 08:54:08 -0700 (PDT) Received: by mail-wm1-x333.google.com with SMTP id n17-20020a7bc5d10000b0290169edfadac9so1920237wmk.1 for ; Tue, 01 Jun 2021 08:54:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=date:from:to:cc:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=WqUgAHrpDOUpUOXO/CHtnZe/20C1L3Tz7SUmh5uKdic=; b=SxNumUnPY4IKba355+/kIgE6CFqG1Es7zT37mTIOq/eyv1lIGuhkg8FVrq3smr+URi 5xsvO7Wzx0zvf2j3d4Hq05GME8N1aL4E7BI37ziX+UqgF5rkdb81qikzEfaL2JucifaF Sex4i9CgwjWyBFaqFyfDNNZrSM4IkoeJekLJs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :in-reply-to; bh=WqUgAHrpDOUpUOXO/CHtnZe/20C1L3Tz7SUmh5uKdic=; b=HXBJGhRMsVgXDqKFklSuGqn3QHZXfEFmYHJGCt4Nncy5eEgO3EY5wbZdffOOT9fmBc 44iUdnP938ZzrXXTSku37v/VbVic3AW7uLq77fXrR0tl63PwJ4QLDTk/CL6pKvMBxgsF FrHCEap22n844NE3ScMbv5n98jlHPAjKXDBM4tXsicF2ckpNIH4l0FxazP2hqYGaCPda Tmtms2cNRhaTgtZpLsrgmzFBSgLLmQeXFU9rOBYIMT2uWGmRZtGm23n3v75917my99ip t8kE2Atupr6cavlyoA6pF7NyZuHFaNEpE7d+nVkxMtp45thBBSD6vEWewCAqCV3oCbiA 9ecw== X-Gm-Message-State: AOAM530CTBVAFQ/wCMbEJiAhUtlDEpqsUI5A1BFU4MMQsHfsGfqW7+zX KtCfH0I7Pp6ZPm+PDsZEVzBigg== X-Received: by 2002:a7b:c4d0:: with SMTP id g16mr566126wmk.147.1622562846945; Tue, 01 Jun 2021 08:54:06 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:57f4:0:efd0:b9e5:5ae6:c2fa]) by smtp.gmail.com with ESMTPSA id h6sm3680020wrt.6.2021.06.01.08.54.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jun 2021 08:54:06 -0700 (PDT) Date: Tue, 1 Jun 2021 17:54:04 +0200 From: Daniel Vetter To: Paul Cercueil Cc: David Airlie , Daniel Vetter , Thomas Zimmermann , Maxime Ripard , list@opendingux.net, linux-mips@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, Neil Armstrong Subject: Re: [PATCH 10/11] drm/ingenic: Add doublescan feature Message-ID: Mail-Followup-To: Paul Cercueil , David Airlie , Thomas Zimmermann , Maxime Ripard , list@opendingux.net, linux-mips@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, Neil Armstrong References: <20210527232104.152577-1-paul@crapouillou.net> <20210527232206.152771-1-paul@crapouillou.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210527232206.152771-1-paul@crapouillou.net> X-Operating-System: Linux phenom 5.10.32scarlett+ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, May 28, 2021 at 12:22:05AM +0100, Paul Cercueil wrote: > A lot of devices with an Ingenic SoC have a weird LCD panel attached, > where the pixels are not square. For instance, the AUO A030JTN01 and > Innolux EJ030NA panels have a resolution of 320x480 with a 4:3 aspect > ratio. > > All userspace applications are built with the assumption that the > pixels are square. To be able to support these devices without too > much effort, add a doublescan feature, which allows the f0 and f1 > planes to be used with only half of the screen's vertical resolution, > where each line of the input is displayed twice. > > This is done using a chained list of DMA descriptors, one descriptor > per output line. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 93 +++++++++++++++++++++-- > 1 file changed, 87 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > index 2761478b16e8..01d8490393d1 100644 > --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > @@ -66,6 +66,8 @@ struct jz_soc_info { > > struct ingenic_gem_object { > struct drm_gem_cma_object base; > + struct ingenic_dma_hwdesc *hwdescs; > + dma_addr_t hwdescs_phys; > }; > > struct ingenic_drm_private_state { > @@ -73,6 +75,23 @@ struct ingenic_drm_private_state { > > bool no_vblank; > bool use_palette; > + > + /* > + * A lot of devices with an Ingenic SoC have a weird LCD panel attached, > + * where the pixels are not square. For instance, the AUO A030JTN01 and > + * Innolux EJ030NA panels have a resolution of 320x480 with a 4:3 aspect > + * ratio. > + * > + * All userspace applications are built with the assumption that the > + * pixels are square. To be able to support these devices without too > + * much effort, add a doublescan feature, which allows the f0 and f1 > + * planes to be used with only half of the screen's vertical resolution, > + * where each line of the input is displayed twice. > + * > + * This is done using a chained list of DMA descriptors, one descriptor > + * per output line. > + */ > + bool doublescan; > }; > > struct ingenic_drm { > @@ -465,7 +484,7 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, > return PTR_ERR(priv_state); > > ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, > - DRM_PLANE_HELPER_NO_SCALING, > + 0x8000, > DRM_PLANE_HELPER_NO_SCALING, > priv->soc_info->has_osd, > true); > @@ -482,6 +501,17 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, > (new_plane_state->src_h >> 16) != new_plane_state->crtc_h)) > return -EINVAL; > > + /* Enable doublescan if the CRTC_H is twice the SRC_H. */ > + priv_state->doublescan = (new_plane_state->src_h >> 16) * 2 == new_plane_state->crtc_h; > + > + /* Otherwise, fail if CRTC_H != SRC_H */ > + if (!priv_state->doublescan && (new_plane_state->src_h >> 16) != new_plane_state->crtc_h) > + return -EINVAL; > + > + /* Fail if CRTC_W != SRC_W */ > + if ((new_plane_state->src_w >> 16) != new_plane_state->crtc_w) > + return -EINVAL; > + > priv_state->use_palette = new_plane_state->fb && > new_plane_state->fb->format->format == DRM_FORMAT_C8; > > @@ -647,7 +677,9 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, > struct ingenic_drm_private_state *priv_state; > struct drm_crtc_state *crtc_state; > struct ingenic_dma_hwdesc *hwdesc; > - unsigned int width, height, cpp; > + unsigned int width, height, cpp, i; > + struct drm_gem_object *gem_obj; > + struct ingenic_gem_object *obj; > dma_addr_t addr, next_addr; > bool use_f1; > u32 fourcc; > @@ -664,17 +696,39 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, > height = newstate->src_h >> 16; > cpp = newstate->fb->format->cpp[0]; > > + gem_obj = drm_gem_fb_get_obj(newstate->fb, 0); > + obj = to_ingenic_gem_obj(gem_obj); > + > priv_state = ingenic_drm_get_new_priv_state(priv, state); > if (priv_state && priv_state->use_palette) > next_addr = dma_hwdesc_pal_addr(priv); > else > next_addr = dma_hwdesc_addr(priv, use_f1); > > - hwdesc = &priv->dma_hwdescs->hwdesc[use_f1]; > + if (priv_state->doublescan) { > + hwdesc = &obj->hwdescs[0]; > + /* > + * Use one DMA descriptor per output line, and display > + * each input line twice. > + */ > + for (i = 0; i < newstate->crtc_h; i++) { > + hwdesc[i].next = obj->hwdescs_phys > + + (i + 1) * sizeof(*hwdesc); > + hwdesc[i].addr = addr + (i / 2) * newstate->fb->pitches[0]; > + hwdesc[i].cmd = newstate->fb->pitches[0] / 4; > + } > > - hwdesc->addr = addr; > - hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); > - hwdesc->next = next_addr; > + /* We want the EOF IRQ only on the very last transfer */ > + hwdesc[newstate->crtc_h - 1].cmd |= JZ_LCD_CMD_EOF_IRQ; > + hwdesc[newstate->crtc_h - 1].next = next_addr; > + priv->dma_hwdescs->hwdesc[use_f1] = *hwdesc; > + } else { > + /* Use one DMA descriptor for the whole frame. */ > + hwdesc = &priv->dma_hwdescs->hwdesc[use_f1]; > + hwdesc->addr = addr; > + hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); > + hwdesc->next = next_addr; > + } > > if (drm_atomic_crtc_needs_modeset(crtc_state)) { > fourcc = newstate->fb->format->format; > @@ -848,6 +902,13 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) > > static void ingenic_drm_gem_fb_destroy(struct drm_framebuffer *fb) > { > + struct ingenic_drm *priv = drm_device_get_priv(fb->dev); > + struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); > + struct ingenic_gem_object *obj = to_ingenic_gem_obj(gem_obj); > + > + dma_free_coherent(priv->dev, > + sizeof(*obj->hwdescs) * fb->height, > + obj->hwdescs, obj->hwdescs_phys); You can have multiple fb pointing at the same gem bo. I think with that this blows up pretty badly. I think right call is to just move the doublescan mapping to the fb object entirely, and not have a subclassed gem bo. Userspace shouldn't recreate fb objects just for fun, so caching at the gem bo level shouldn't be needed. But if you do need it then you need to refcount it so multiple fb objects all work out (and they can have different modes even used for them). Another option is attaching this to the drm_plane state and setting it up in prepare_plane/cleanup_plane. But then you probably need some caching at the obj level (but a simple single slot/last hit cache should be good enough here). I think this would be the cleanest since doing very expensive things attached to fb might cause issues, userspace can create/destroy quite a few of them as part of atomic_test (which skips the prepare/cleanup_plane part). So this would be the right option if setting up this dma mapping for doublescan is a more expensive thing to do. -Daniel > drm_gem_fb_destroy(fb); > } > > @@ -868,6 +929,8 @@ ingenic_drm_gem_fb_create(struct drm_device *drm, struct drm_file *file, > { > struct ingenic_drm *priv = drm_device_get_priv(drm); > const struct drm_framebuffer_funcs *fb_funcs; > + struct drm_gem_object *gem_obj; > + struct ingenic_gem_object *obj; > struct drm_framebuffer *fb; > > if (priv->soc_info->map_noncoherent) > @@ -876,6 +939,24 @@ ingenic_drm_gem_fb_create(struct drm_device *drm, struct drm_file *file, > fb_funcs = &ingenic_drm_gem_fb_funcs; > > fb = drm_gem_fb_create_with_funcs(drm, file, mode_cmd, fb_funcs); > + if (IS_ERR(fb)) > + return fb; > + > + gem_obj = drm_gem_fb_get_obj(fb, 0); > + obj = to_ingenic_gem_obj(gem_obj); > + > + /* > + * Create (fb->height * 2) DMA descriptors, in case we want to use the > + * doublescan feature. > + */ > + obj->hwdescs = dma_alloc_coherent(priv->dev, > + sizeof(*obj->hwdescs) * fb->height * 2, > + &obj->hwdescs_phys, > + GFP_KERNEL); > + if (!obj->hwdescs) { > + drm_gem_fb_destroy(fb); > + return ERR_PTR(-ENOMEM); > + } > > return fb; > } > -- > 2.30.2 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch