Received: by 2002:ac0:950e:0:0:0:0:0 with SMTP id f14csp752715imc; Sat, 16 Mar 2019 15:02:21 -0700 (PDT) X-Google-Smtp-Source: APXvYqx7jHlq33D90irnQWJi4dUYDG3k2V4g2WSyyXP6KH469ToiVTm9693nRCe5NxPKFatUpwBY X-Received: by 2002:a62:4414:: with SMTP id r20mr11340400pfa.37.1552773740976; Sat, 16 Mar 2019 15:02:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1552773740; cv=none; d=google.com; s=arc-20160816; b=vRjoW1F0HwbErO9IUGhCwCjmFbV9tOeQylycIPVOmErMqYyKsQNlrrjVUEXwBpT0Ga J/H3P6tk26krLEB0VzQwhOUrI+jh4sCKb/5w6UZy2q8pDZ+UH5mtMCspO4NnZXn8x2t+ AY5MrKfYGxVoQBaAECjzWetJAKSxQ2eyrDlD+5NGJzftco/VqLJO9OOfPdGn5QxB9lqM p2f15h4KMtyEhh98ZffUiqnReVu7VgFlLLFD7pAdtLvs4NijSa5/p0PRzI1ktaBrPllG gHdT4RDs6alj007Ev6PBhGlMFci31P07Y6Z1WzfsddrTmYTiNTaH8EzZ8/2aUx5yUgES E3RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=j6Gp2y7SF9g7qEk6fySlgDrjq7hJ2VPzuXajQT7uNdo=; b=DSMouj80TwMENE+8MKNCAnBRuJ7Ju3XmRnQc6Hb2C7+273432Nl2ieJvx9LSs4CeWU XGsdKPVWxF/34xghU+2twsZyHqRz2ntAxMrrM5PJ3uE3s7TJx5GIV8zwVbCEKSACPDtW SLRKC6HS4A9AcPh2++LabubJuSTgJthorQpQ8wxqX+VBe06/CItnlzOz8GGxHMD979Sm YL91psBorAMsU8K8VcerpHCdpugGHTS190Ece1b2Q6mNZ5NViQRda6BSBoidc5QLX6na dMnf89RYpYPHCWsgmnQjTdn8GT84mOkUKzIt+KTOSvPfxscbO7ICVmgXFbdAV05ZcdaY e+VA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k127si5206748pgc.124.2019.03.16.15.02.05; Sat, 16 Mar 2019 15:02:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726741AbfCPV7w (ORCPT + 99 others); Sat, 16 Mar 2019 17:59:52 -0400 Received: from asavdk3.altibox.net ([109.247.116.14]:41328 "EHLO asavdk3.altibox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726349AbfCPV7w (ORCPT ); Sat, 16 Mar 2019 17:59:52 -0400 Received: from ravnborg.org (unknown [158.248.194.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by asavdk3.altibox.net (Postfix) with ESMTPS id 14057200C3; Sat, 16 Mar 2019 22:59:46 +0100 (CET) Date: Sat, 16 Mar 2019 22:59:44 +0100 From: Sam Ravnborg To: Paul Cercueil Cc: David Airlie , Daniel Vetter , Rob Herring , Mark Rutland , Maarten Lankhorst , Maxime Ripard , Sean Paul , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: Re: [PATCH v2 3/3] DRM: Add KMS driver for the Ingenic JZ47xx SoCs Message-ID: <20190316215944.GB11309@ravnborg.org> References: <20190315170701.29670-1-paul@crapouillou.net> <20190315170701.29670-3-paul@crapouillou.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20190315170701.29670-3-paul@crapouillou.net> User-Agent: Mutt/1.5.21 (2010-09-15) X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=dqr19Wo4 c=1 sm=1 tr=0 a=UWs3HLbX/2nnQ3s7vZ42gw==:117 a=UWs3HLbX/2nnQ3s7vZ42gw==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=kj9zAlcOel0A:10 a=ER_8r6IbAAAA:8 a=p6pI0oa4AAAA:8 a=3iZPsmZ1dwio5CCrdjoA:9 a=CjuIK1q_8ugA:10 a=9LHmKk7ezEChjTCyhBa9:22 a=9cw2y2bKwytFd151gpuR:22 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Paul. Thanks for the v2 submission. Did you analyze the possibility to utilize drm_simple_display_pipe_init() and the related infrastructure? If this fits it should simplify the driver. If it does not fit please let us know why. As this is a one crtc / one connector / one panel the drm_simple_* infrastructure is supposed to be a good fit. Some smaller comments in the following. Most are suggestion, do not follow these blindly. Sam > Add a KMS driver for the Ingenic JZ47xx family of SoCs. > This driver is meant to replace the aging jz4740-fb driver. > > Signed-off-by: Paul Cercueil > Tested-by: Artur Rojek > +struct ingenic_drm { > + struct device *dev; > + void __iomem *base; > + struct regmap *map; > + struct clk *lcd_clk, *pix_clk; > + > + u32 lcd_mode; > + > + struct ingenic_dma_hwdesc *framedesc; Consider the name "dma_hwdesc" for this. The struct is named so, which give a good indication this is a more descriptive name. That said, the current solution looks much cleaner than the previous one. > + dma_addr_t framedesc_phys; Likewise. > + > + struct drm_device *drm; If drm is embedded you can use devm_drm_dev_init() recently added to drm-misc. See the very nice example in drivers/gu/drm/drm_drv.c (only in drm-misc-next for now) > + struct drm_plane primary; > + struct drm_crtc crtc; > + struct drm_encoder encoder; > +}; > + > + > +static int ingenic_drm_probe(struct platform_device *pdev) > +{ > + const struct jz_soc_info *soc_info; > + struct device *dev = &pdev->dev; > + struct ingenic_drm *priv; > + struct clk *parent_clk; > + struct drm_bridge *bridge; > + struct drm_panel *panel; > + struct drm_device *drm; > + struct resource *mem; > + void __iomem *base; > + long parent_rate; > + int ret, irq; > + > + soc_info = device_get_match_data(dev); Everyone else uses of_device_... here. You should most likely do the same. > + if (!soc_info) > + return -EINVAL; Also, consider to print an error here. > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; Use of devm_kzalloc() here is not good. See driver example in drm_drv.c > + > + priv->dev = dev; > + > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + priv->base = base = devm_ioremap_resource(dev, mem); > + if (IS_ERR(base)) > + return PTR_ERR(base); > + > + irq = platform_get_irq(pdev, 0); > + if (irq < 0) { > + dev_err(dev, "Failed to get platform irq\n"); > + return -ENOENT; > + } > + > + priv->map = devm_regmap_init_mmio(dev, base, > + &ingenic_drm_regmap_config); > + if (IS_ERR(priv->map)) { > + dev_err(dev, "Failed to create regmap\n"); > + return PTR_ERR(priv->map); > + } > + > + if (soc_info->needs_dev_clk) { > + priv->lcd_clk = devm_clk_get(dev, "lcd"); > + if (IS_ERR(priv->lcd_clk)) { > + dev_err(dev, "Failed to get lcd clock\n"); > + return PTR_ERR(priv->lcd_clk); > + } > + } > + > + priv->pix_clk = devm_clk_get(dev, "lcd_pclk"); > + if (IS_ERR(priv->pix_clk)) { > + dev_err(dev, "Failed to get pixel clock\n"); > + return PTR_ERR(priv->pix_clk); > + } > + > + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge); > + if (ret) { > + if (ret != -EPROBE_DEFER) > + dev_err(dev, "Failed to get panel handle\n"); > + return ret; > + } > + > + if (panel) { > + bridge = devm_drm_panel_bridge_add(dev, panel, > + DRM_MODE_CONNECTOR_Unknown); > + } > + > + device_property_read_u32(dev, "ingenic,lcd-mode", &priv->lcd_mode); > + > + priv->framedesc = dma_alloc_coherent(dev, sizeof(*priv->framedesc), > + &priv->framedesc_phys, GFP_KERNEL); > + if (!priv->framedesc) > + return -ENOMEM; > + > + priv->framedesc->next = priv->framedesc_phys; > + priv->framedesc->id = 0xdeafbead; > + > + drm = drm_dev_alloc(&ingenic_drm_driver_data, dev); > + if (IS_ERR(drm)) { > + ret = PTR_ERR(drm); > + goto err_free_dma; > + } > + > + priv->drm = drm; > + > + drm_mode_config_init(drm); > + drm->mode_config.min_width = 0; > + drm->mode_config.min_height = 0; > + drm->mode_config.max_width = 800; > + drm->mode_config.max_height = 600; > + drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; > + > + drm_plane_helper_add(&priv->primary, &ingenic_drm_plane_helper_funcs); > + > + ret = drm_universal_plane_init(drm, &priv->primary, > + 0, &ingenic_drm_primary_plane_funcs, > + ingenic_drm_primary_formats, > + ARRAY_SIZE(ingenic_drm_primary_formats), > + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); > + if (ret) { > + dev_err(dev, "Failed to register primary plane: %i\n", ret); > + goto err_unref_drm; > + } > + > + drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); > + > + ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->primary, > + NULL, &ingenic_drm_crtc_funcs, NULL); > + if (ret) { > + dev_err(dev, "Failed to init CRTC: %i\n", ret); > + goto err_cleanup_plane; > + } > + > + priv->encoder.possible_crtcs = 1; > + > + drm_encoder_helper_add(&priv->encoder, > + &ingenic_drm_encoder_helper_funcs); > + > + ret = drm_encoder_init(drm, &priv->encoder, &ingenic_drm_encoder_funcs, > + DRM_MODE_ENCODER_DPI, NULL); > + if (ret) { > + dev_err(dev, "Failed to init encoder: %i\n", ret); > + goto err_cleanup_crtc; > + } > + > + ret = drm_bridge_attach(&priv->encoder, bridge, NULL); > + if (ret) { > + dev_err(dev, "Unable to attach bridge\n"); > + goto err_cleanup_encoder; > + } > + > + platform_set_drvdata(pdev, drm); > + priv->drm = drm; > + drm->dev_private = priv; > + > + ret = drm_irq_install(drm, irq); > + if (ret) { > + dev_err(dev, "Unable to install IRQ handler\n"); > + goto err_cleanup_encoder; > + } > + > + ret = drm_vblank_init(drm, 1); > + if (ret) { > + dev_err(dev, "Failed calling drm_vblank_init()\n"); > + goto err_uninstall_irq; > + } > + > + drm_mode_config_reset(drm); > + > + ret = clk_prepare_enable(priv->pix_clk); > + if (ret) { > + dev_err(dev, "Unable to start pixel clock\n"); > + goto err_uninstall_irq; > + } > + > + if (priv->lcd_clk) { > + parent_clk = clk_get_parent(priv->lcd_clk); > + parent_rate = clk_get_rate(parent_clk); > + > + /* LCD Device clock must be 3x the pixel clock for STN panels, > + * or 1.5x the pixel clock for TFT panels. To avoid having to > + * check for the LCD device clock everytime we do a mode change, > + * we set the LCD device clock to the highest rate possible. > + */ > + ret = clk_set_rate(priv->lcd_clk, parent_rate); > + if (ret) { > + dev_err(dev, "Unable to set LCD clock rate\n"); > + goto err_pixclk_disable; > + } > + > + ret = clk_prepare_enable(priv->lcd_clk); > + if (ret) { > + dev_err(dev, "Unable to start lcd clock\n"); > + goto err_pixclk_disable; > + } > + } > + > + ret = drm_fbdev_generic_setup(drm, 16); > + if (ret) { > + dev_err(dev, "Failed to init fbdev\n"); > + goto err_devclk_disable; > + } fbdev is usually considered an optionl feature that do not prevent the display driver from loading. Consider what to do in the error case.