From: Jianhua Lu <lujianhua000@gmail.com>
To: Konrad Dybcio <konrad.dybcio@linaro.org>
Cc: Thierry Reding <thierry.reding@gmail.com>,
Sam Ravnborg <sam@ravnborg.org>, David Airlie <airlied@gmail.com>,
Daniel Vetter <daniel@ffwll.ch>, Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Linus Walleij <linus.walleij@linaro.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
~postmarketos/upstreaming@lists.sr.ht,
phone-devel@vger.kernel.org
Subject: Re: [PATCH v4 2/2] drm/panel: Add driver for Novatek NT36523
Date: Sat, 11 Mar 2023 02:35:41 +0800 [thread overview]
Message-ID: <ZAt4fTNEnyLteaas@Gentoo> (raw)
In-Reply-To: <6539f132-c740-b9b6-8810-0affd6ab91ba@linaro.org>
On Fri, Mar 10, 2023 at 07:10:21PM +0100, Konrad Dybcio wrote:
>
> > +#define mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, cmd, seq...) \
> > + do { \
> > + mipi_dsi_dcs_write_seq(dsi0, cmd, seq); \
> > + mipi_dsi_dcs_write_seq(dsi1, cmd, seq); \
> > + } while (0)
> This should be in the same file as mipi_dsi_dcs_write_seq, imo
I have sent a patch to do it, upstream don't think this wrapper is a proper
approach to deal with dual dsi and wrap all of mipi_dsi_* function is
useless.
https://lore.kernel.org/lkml/20230310110542.6649-1-lujianhua000@gmail.com/
>
> [...]
>
> > +static int elish_boe_init_sequence(struct panel_info *pinfo)
> > +{
> > + struct mipi_dsi_device *dsi0 = pinfo->dsi[0];
> > + struct mipi_dsi_device *dsi1 = pinfo->dsi[1];
> > + /* No datasheet, so write magic init sequence directly */
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xFF, 0x10);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xFB, 0x01);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xB9, 0x05);
> Non-#defines should use lowercase hex
Acked
>
> [...]
>
> > + msleep(70);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29);
> > + return 0;
> I think it's a general practice to add a newline before the return
> statement, but that's just a nit that triggered my OCD..
Acked
>
> [...]
>
> > + struct drm_connector *connector)
> > +{
> > + struct panel_info *pinfo = to_panel_info(panel);
> > + int i;
> > +
> > + for (i =0; i < pinfo->desc->num_modes; i++) {
> missing space after =
Acked
> > + const struct drm_display_mode *m = &pinfo->desc->modes[i];
> > + struct drm_display_mode *mode;
> Missing newline between declarations and code
Acked
>
> > + mode = drm_mode_duplicate(connector->dev, m);
> > + if (!mode) {
> > + dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
> > + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
> > + return -ENOMEM;
> > + }
> > + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native resolution of an LCD panel. There should only be one preferred mode per connector at any given time.
>
> https://docs.kernel.org/gpu/drm-kms.html
>
> I'd suggest adding something like:
>
> if (i == 0)
> mode->type |= DRM_MODE_TYPE_PREFERRED
>
Acked
>
> I think I've ran out of things to complain about.. And that's
> a good thing! :D
>
> Konrad
> > + drm_mode_set_name(mode);
> > + drm_mode_probed_add(connector, mode);
> > + }
> > +
> > + connector->display_info.width_mm = pinfo->desc->width_mm;
> > + connector->display_info.height_mm = pinfo->desc->height_mm;
> > + connector->display_info.bpc = pinfo->desc->bpc;
> > +
> > + return pinfo->desc->num_modes;
> > +}
> > +
> > +static const struct drm_panel_funcs nt36523_panel_funcs = {
> > + .disable = nt36523_disable,
> > + .prepare = nt36523_prepare,
> > + .unprepare = nt36523_unprepare,
> > + .get_modes = nt36523_get_modes,
> > +};
> > +
> > +static int nt36523_probe(struct mipi_dsi_device *dsi)
> > +{
> > + struct device *dev = &dsi->dev;
> > + struct device_node *dsi1;
> > + struct mipi_dsi_host *dsi1_host;
> > + struct panel_info *pinfo;
> > + const struct mipi_dsi_device_info *info;
> > + int i, ret;
> > +
> > + pinfo = devm_kzalloc(dev, sizeof(*pinfo), GFP_KERNEL);
> > + if (!pinfo)
> > + return -ENOMEM;
> > +
> > + pinfo->vddio = devm_regulator_get(dev, "vddio");
> > + if (IS_ERR(pinfo->vddio))
> > + return dev_err_probe(dev, PTR_ERR(pinfo->vddio), "failed to get vddio regulator\n");
> > +
> > + pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> > + if (IS_ERR(pinfo->reset_gpio))
> > + return dev_err_probe(dev, PTR_ERR(pinfo->reset_gpio), "failed to get reset gpio\n");
> > +
> > + pinfo->desc = of_device_get_match_data(dev);
> > + if (!pinfo->desc)
> > + return -ENODEV;
> > +
> > + /* If the panel is dual dsi, register DSI1 */
> > + if (pinfo->desc->is_dual_dsi) {
> > + info = &pinfo->desc->dsi_info;
> > +
> > + dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
> > + if (!dsi1) {
> > + dev_err(dev, "cannot get secondary DSI node.\n");
> > + return -ENODEV;
> > + }
> > +
> > + dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
> > + of_node_put(dsi1);
> > + if (!dsi1_host) {
> > + return dev_err_probe(dev, -EPROBE_DEFER, "cannot get secondary DSI host\n");
> > + }
> > +
> > + pinfo->dsi[1] = mipi_dsi_device_register_full(dsi1_host, info);
> > + if (!pinfo->dsi[1]) {
> > + dev_err(dev, "cannot get secondary DSI device\n");
> > + return -ENODEV;
> > + }
> > + }
> > +
> > + pinfo->dsi[0] = dsi;
> > + mipi_dsi_set_drvdata(dsi, pinfo);
> > + drm_panel_init(&pinfo->panel, dev, &nt36523_panel_funcs, DRM_MODE_CONNECTOR_DSI);
> > +
> > + ret = drm_panel_of_backlight(&pinfo->panel);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "failed to get backlight\n");
> > +
> > + drm_panel_add(&pinfo->panel);
> > +
> > + for (i = 0; i < DSI_NUM_MIN + pinfo->desc->is_dual_dsi; i++) {
> > + pinfo->dsi[i]->lanes = pinfo->desc->lanes;
> > + pinfo->dsi[i]->format = pinfo->desc->format;
> > + pinfo->dsi[i]->mode_flags = pinfo->desc->mode_flags;
> > +
> > + ret = mipi_dsi_attach(pinfo->dsi[i]);
> > + if (ret < 0)
> > + return dev_err_probe(dev, ret, "cannot attach to DSI%d host.\n", i);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id nt36523_of_match[] = {
> > + {
> > + .compatible = "xiaomi,elish-boe-nt36523",
> > + .data = &elish_boe_desc,
> > + },
> > + {
> > + .compatible = "xiaomi,elish-csot-nt36523",
> > + .data = &elish_csot_desc,
> > + },
> > + {},
> > +};
> > +MODULE_DEVICE_TABLE(of, nt36523_of_match);
> > +
> > +static struct mipi_dsi_driver nt36523_driver = {
> > + .probe = nt36523_probe,
> > + .remove = nt36523_remove,
> > + .driver = {
> > + .name = "panel-novatek-nt36523",
> > + .of_match_table = nt36523_of_match,
> > + },
> > +};
> > +module_mipi_dsi_driver(nt36523_driver);
> > +
> > +MODULE_AUTHOR("Jianhua Lu <lujianhua000@gmail.com>");
> > +MODULE_DESCRIPTION("DRM driver for Novatek NT36523 based MIPI DSI panels");
> > +MODULE_LICENSE("GPL");
WARNING: multiple messages have this Message-ID (diff)
From: Jianhua Lu <lujianhua000@gmail.com>
To: Konrad Dybcio <konrad.dybcio@linaro.org>
Cc: Neil Armstrong <neil.armstrong@linaro.org>,
devicetree@vger.kernel.org, Sam Ravnborg <sam@ravnborg.org>,
linux-kernel@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
Thierry Reding <thierry.reding@gmail.com>,
dri-devel@lists.freedesktop.org,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
phone-devel@vger.kernel.org,
~postmarketos/upstreaming@lists.sr.ht
Subject: Re: [PATCH v4 2/2] drm/panel: Add driver for Novatek NT36523
Date: Sat, 11 Mar 2023 02:35:41 +0800 [thread overview]
Message-ID: <ZAt4fTNEnyLteaas@Gentoo> (raw)
In-Reply-To: <6539f132-c740-b9b6-8810-0affd6ab91ba@linaro.org>
On Fri, Mar 10, 2023 at 07:10:21PM +0100, Konrad Dybcio wrote:
>
> > +#define mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, cmd, seq...) \
> > + do { \
> > + mipi_dsi_dcs_write_seq(dsi0, cmd, seq); \
> > + mipi_dsi_dcs_write_seq(dsi1, cmd, seq); \
> > + } while (0)
> This should be in the same file as mipi_dsi_dcs_write_seq, imo
I have sent a patch to do it, upstream don't think this wrapper is a proper
approach to deal with dual dsi and wrap all of mipi_dsi_* function is
useless.
https://lore.kernel.org/lkml/20230310110542.6649-1-lujianhua000@gmail.com/
>
> [...]
>
> > +static int elish_boe_init_sequence(struct panel_info *pinfo)
> > +{
> > + struct mipi_dsi_device *dsi0 = pinfo->dsi[0];
> > + struct mipi_dsi_device *dsi1 = pinfo->dsi[1];
> > + /* No datasheet, so write magic init sequence directly */
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xFF, 0x10);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xFB, 0x01);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xB9, 0x05);
> Non-#defines should use lowercase hex
Acked
>
> [...]
>
> > + msleep(70);
> > + mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29);
> > + return 0;
> I think it's a general practice to add a newline before the return
> statement, but that's just a nit that triggered my OCD..
Acked
>
> [...]
>
> > + struct drm_connector *connector)
> > +{
> > + struct panel_info *pinfo = to_panel_info(panel);
> > + int i;
> > +
> > + for (i =0; i < pinfo->desc->num_modes; i++) {
> missing space after =
Acked
> > + const struct drm_display_mode *m = &pinfo->desc->modes[i];
> > + struct drm_display_mode *mode;
> Missing newline between declarations and code
Acked
>
> > + mode = drm_mode_duplicate(connector->dev, m);
> > + if (!mode) {
> > + dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
> > + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
> > + return -ENOMEM;
> > + }
> > + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native resolution of an LCD panel. There should only be one preferred mode per connector at any given time.
>
> https://docs.kernel.org/gpu/drm-kms.html
>
> I'd suggest adding something like:
>
> if (i == 0)
> mode->type |= DRM_MODE_TYPE_PREFERRED
>
Acked
>
> I think I've ran out of things to complain about.. And that's
> a good thing! :D
>
> Konrad
> > + drm_mode_set_name(mode);
> > + drm_mode_probed_add(connector, mode);
> > + }
> > +
> > + connector->display_info.width_mm = pinfo->desc->width_mm;
> > + connector->display_info.height_mm = pinfo->desc->height_mm;
> > + connector->display_info.bpc = pinfo->desc->bpc;
> > +
> > + return pinfo->desc->num_modes;
> > +}
> > +
> > +static const struct drm_panel_funcs nt36523_panel_funcs = {
> > + .disable = nt36523_disable,
> > + .prepare = nt36523_prepare,
> > + .unprepare = nt36523_unprepare,
> > + .get_modes = nt36523_get_modes,
> > +};
> > +
> > +static int nt36523_probe(struct mipi_dsi_device *dsi)
> > +{
> > + struct device *dev = &dsi->dev;
> > + struct device_node *dsi1;
> > + struct mipi_dsi_host *dsi1_host;
> > + struct panel_info *pinfo;
> > + const struct mipi_dsi_device_info *info;
> > + int i, ret;
> > +
> > + pinfo = devm_kzalloc(dev, sizeof(*pinfo), GFP_KERNEL);
> > + if (!pinfo)
> > + return -ENOMEM;
> > +
> > + pinfo->vddio = devm_regulator_get(dev, "vddio");
> > + if (IS_ERR(pinfo->vddio))
> > + return dev_err_probe(dev, PTR_ERR(pinfo->vddio), "failed to get vddio regulator\n");
> > +
> > + pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> > + if (IS_ERR(pinfo->reset_gpio))
> > + return dev_err_probe(dev, PTR_ERR(pinfo->reset_gpio), "failed to get reset gpio\n");
> > +
> > + pinfo->desc = of_device_get_match_data(dev);
> > + if (!pinfo->desc)
> > + return -ENODEV;
> > +
> > + /* If the panel is dual dsi, register DSI1 */
> > + if (pinfo->desc->is_dual_dsi) {
> > + info = &pinfo->desc->dsi_info;
> > +
> > + dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
> > + if (!dsi1) {
> > + dev_err(dev, "cannot get secondary DSI node.\n");
> > + return -ENODEV;
> > + }
> > +
> > + dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
> > + of_node_put(dsi1);
> > + if (!dsi1_host) {
> > + return dev_err_probe(dev, -EPROBE_DEFER, "cannot get secondary DSI host\n");
> > + }
> > +
> > + pinfo->dsi[1] = mipi_dsi_device_register_full(dsi1_host, info);
> > + if (!pinfo->dsi[1]) {
> > + dev_err(dev, "cannot get secondary DSI device\n");
> > + return -ENODEV;
> > + }
> > + }
> > +
> > + pinfo->dsi[0] = dsi;
> > + mipi_dsi_set_drvdata(dsi, pinfo);
> > + drm_panel_init(&pinfo->panel, dev, &nt36523_panel_funcs, DRM_MODE_CONNECTOR_DSI);
> > +
> > + ret = drm_panel_of_backlight(&pinfo->panel);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "failed to get backlight\n");
> > +
> > + drm_panel_add(&pinfo->panel);
> > +
> > + for (i = 0; i < DSI_NUM_MIN + pinfo->desc->is_dual_dsi; i++) {
> > + pinfo->dsi[i]->lanes = pinfo->desc->lanes;
> > + pinfo->dsi[i]->format = pinfo->desc->format;
> > + pinfo->dsi[i]->mode_flags = pinfo->desc->mode_flags;
> > +
> > + ret = mipi_dsi_attach(pinfo->dsi[i]);
> > + if (ret < 0)
> > + return dev_err_probe(dev, ret, "cannot attach to DSI%d host.\n", i);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id nt36523_of_match[] = {
> > + {
> > + .compatible = "xiaomi,elish-boe-nt36523",
> > + .data = &elish_boe_desc,
> > + },
> > + {
> > + .compatible = "xiaomi,elish-csot-nt36523",
> > + .data = &elish_csot_desc,
> > + },
> > + {},
> > +};
> > +MODULE_DEVICE_TABLE(of, nt36523_of_match);
> > +
> > +static struct mipi_dsi_driver nt36523_driver = {
> > + .probe = nt36523_probe,
> > + .remove = nt36523_remove,
> > + .driver = {
> > + .name = "panel-novatek-nt36523",
> > + .of_match_table = nt36523_of_match,
> > + },
> > +};
> > +module_mipi_dsi_driver(nt36523_driver);
> > +
> > +MODULE_AUTHOR("Jianhua Lu <lujianhua000@gmail.com>");
> > +MODULE_DESCRIPTION("DRM driver for Novatek NT36523 based MIPI DSI panels");
> > +MODULE_LICENSE("GPL");
next prev parent reply other threads:[~2023-03-10 18:35 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-10 13:21 [PATCH v4 1/2] dt-bindings: display: panel: Add Novatek NT36523 bindings Jianhua Lu
2023-03-10 13:21 ` Jianhua Lu
2023-03-10 13:21 ` [PATCH v4 2/2] drm/panel: Add driver for Novatek NT36523 Jianhua Lu
2023-03-10 13:21 ` Jianhua Lu
2023-03-10 16:57 ` Neil Armstrong
2023-03-10 16:57 ` Neil Armstrong
2023-03-10 18:07 ` Jianhua Lu
2023-03-10 18:07 ` Jianhua Lu
2023-03-10 18:10 ` Konrad Dybcio
2023-03-10 18:10 ` Konrad Dybcio
2023-03-10 18:35 ` Jianhua Lu [this message]
2023-03-10 18:35 ` Jianhua Lu
2023-03-10 22:50 ` Linus Walleij
2023-03-10 22:50 ` Linus Walleij
2023-03-11 10:05 ` Neil Armstrong
2023-03-11 10:05 ` Neil Armstrong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZAt4fTNEnyLteaas@Gentoo \
--to=lujianhua000@gmail.com \
--cc=airlied@gmail.com \
--cc=daniel@ffwll.ch \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=konrad.dybcio@linaro.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linus.walleij@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=phone-devel@vger.kernel.org \
--cc=robh+dt@kernel.org \
--cc=sam@ravnborg.org \
--cc=thierry.reding@gmail.com \
--cc=~postmarketos/upstreaming@lists.sr.ht \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.