From patchwork Thu Jan 9 05:13:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhou Zhu X-Patchwork-Id: 3457351 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E9CBDC02DC for ; Thu, 9 Jan 2014 05:13:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9BE2E2015B for ; Thu, 9 Jan 2014 05:13:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3C5512014A for ; Thu, 9 Jan 2014 05:13:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751060AbaAIFNR (ORCPT ); Thu, 9 Jan 2014 00:13:17 -0500 Received: from mx0b-0016f401.pphosted.com ([67.231.156.173]:45234 "EHLO mx0b-0016f401.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751024AbaAIFNQ (ORCPT ); Thu, 9 Jan 2014 00:13:16 -0500 Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.14.5/8.14.5) with SMTP id s095DCDM013470; Wed, 8 Jan 2014 21:13:12 -0800 Received: from sc-owa01.marvell.com ([199.233.58.136]) by mx0b-0016f401.pphosted.com with ESMTP id 1h919rbbf0-26 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NOT); Wed, 08 Jan 2014 21:13:12 -0800 Received: from maili.marvell.com (10.93.76.43) by sc-owa01.marvell.com (10.93.76.21) with Microsoft SMTP Server id 8.3.327.1; Wed, 8 Jan 2014 21:13:05 -0800 Received: from localhost (unknown [10.38.36.157]) by maili.marvell.com (Postfix) with ESMTP id A6C1E1CCDC1; Wed, 8 Jan 2014 21:13:05 -0800 (PST) From: Zhou Zhu To: , Tomi Valkeinen , Jean-Christophe Plagniol-Villard CC: Haojian Zhuang , Chao Xie , Guoqing Li , Zhou Zhu Subject: [PATCH] video: mmp: add device tree support Date: Thu, 9 Jan 2014 13:13:14 +0800 Message-ID: <1389244394-10779-1-git-send-email-zzhu3@marvell.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.11.87, 1.0.14, 0.0.0000 definitions=2014-01-09_02:2014-01-07, 2014-01-09, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1305240000 definitions=main-1401080226 Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP add device tree support for mmp fb/controller the description at Documentation/devicetree/bindings/fb/mmp-disp.txt Signed-off-by: Zhou Zhu --- Documentation/devicetree/bindings/fb/mmp-disp.txt | 71 ++++++++++++ drivers/video/mmp/fb/mmpfb.c | 71 ++++++++---- drivers/video/mmp/hw/mmp_ctrl.c | 120 ++++++++++++++++----- 3 files changed, 217 insertions(+), 45 deletions(-) create mode 100644 Documentation/devicetree/bindings/fb/mmp-disp.txt diff --git a/Documentation/devicetree/bindings/fb/mmp-disp.txt b/Documentation/devicetree/bindings/fb/mmp-disp.txt new file mode 100644 index 0000000..3cf2903 --- /dev/null +++ b/Documentation/devicetree/bindings/fb/mmp-disp.txt @@ -0,0 +1,71 @@ +* Marvell MMP Display (MMP_DISP) + +To config mmp display, 3 parts are required to be set in dts: +1. mmp fb +Required properties: +- compatible: Should be "marvell,mmp-fb". +- marvell,fb-name: Should be the name of this fb. +- marvell,path-name: Should be the name of path this fb connecting to. +- marvell,overlay-id: Should be the id of overlay this fb is on. +- marvell,dmafetch-id: Should be the dma fetch id this fb using. +- marvell,default-pixfmt: Should be the default pixel format when this fb is +turned on. + +2. mmp controller +Required properties: +- compatible: Should be "marvell,mmp-disp". +- reg: Should be address and length of the register set for this controller. +- interrupts: Should be interrupt of this controller. +- marvell,disp-name: Should be name of this controller +- marvell,path-num: Should be path number exists in this controller. +- marvell,clk-name: Should be name of clock this controller using. + +Required sub-node: +- path: +Required properties in this sub-node: +-- marvell,path-name: Should be name of this path, fb/panel uses this name to +connect to this path. +-- marvell,overlay_num: Should be number of overlay this path has. +-- marvell,output-type: Should be output-type settings +-- marvell,path-config: Should be path-config settings +-- marvell,link-config: Should be link-config settings +-- marvell,rbswap: Should be rbswap settings + +3. panel +Required properties: +- marvell,path-name: Should be path name that this panel connected to. +- other properties each panel has. + +Examples: + +fb: fb { + compatible = "marvell,mmp-fb"; + marvell,fb-name = "mmp_fb"; + marvell,path-name = "mmp_pnpath"; + marvell,overlay-id = <0>; + marvell,dmafetch-id = <1>; + marvell,default-pixfmt = <0x108>; +}; + +disp: disp@d420b000 { + compatible = "marvell,mmp-disp"; + reg = <0xd420b000 0x1fc>; + interrupts = <0 41 0x4>; + marvell,disp-name = "mmp_disp"; + marvell,path-num = <1>; + marvell,clk-name = "LCDCIHCLK"; + path1 { + marvell,path-name = "mmp_pnpath"; + marvell,overlay-num = <2>; + marvell,output-type = <0>; + marvell,path-config = <0x20000000>; + marvell,link-config = <0x60000001>; + marvell,rbswap = <0>; + }; +}; + +panel: { + ... + marvell,path-name = "mmp_pnpath"; + ... +}; diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c index 7ab31eb..e84a411 100644 --- a/drivers/video/mmp/fb/mmpfb.c +++ b/drivers/video/mmp/fb/mmpfb.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "mmpfb.h" static int var_to_pixfmt(struct fb_var_screeninfo *var) @@ -551,56 +553,86 @@ static void fb_info_clear(struct fb_info *info) fb_dealloc_cmap(&info->cmap); } +#ifdef CONFIG_OF +static const struct of_device_id mmp_fb_dt_match[] = { + { .compatible = "marvell,mmp-fb" }, + {}, +}; +#endif + static int mmpfb_probe(struct platform_device *pdev) { +#ifdef CONFIG_OF + struct device_node *np; +#else struct mmp_buffer_driver_mach_info *mi; +#endif struct fb_info *info = 0; struct mmpfb_info *fbi = 0; - int ret, modes_num; - - mi = pdev->dev.platform_data; - if (mi == NULL) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } + int ret = -EINVAL, modes_num; + int overlay_id, dmafetch_id; + const char *path_name; /* initialize fb */ info = framebuffer_alloc(sizeof(struct mmpfb_info), &pdev->dev); if (info == NULL) return -ENOMEM; fbi = info->par; - if (!fbi) { - ret = -EINVAL; + if (!fbi) + goto failed; + +#ifdef CONFIG_OF + np = pdev->dev.of_node; + + if (!np || of_property_read_string(np, + "marvell,fb-name", &fbi->name) || + of_property_read_string(np, + "marvell,path-name", &path_name) || + of_property_read_u32(np, + "marvell,overlay-id", &overlay_id) || + of_property_read_u32(np, + "marvell,dmafetch-id", &dmafetch_id) || + of_property_read_u32(np, + "marvell,default-pixfmt", &fbi->pix_fmt)) { + dev_err(&pdev->dev, "unable to get fb setting from dt\n"); goto failed; } +#else + mi = pdev->dev.platform_data; + if (mi == NULL) { + dev_err(&pdev->dev, "no platform data defined\n"); + goto failed; + } + fbi->name = mi->name; + path_name = mi->path_name; + overlay_id = mi->overlay_id; + dmafetch_id = mi->dmafetch_id; + fbi->pix_fmt = mi->default_pixfmt; +#endif /* init fb */ fbi->fb_info = info; platform_set_drvdata(pdev, fbi); fbi->dev = &pdev->dev; - fbi->name = mi->name; - fbi->pix_fmt = mi->default_pixfmt; pixfmt_to_var(&info->var, fbi->pix_fmt); mutex_init(&fbi->access_ok); /* get display path by name */ - fbi->path = mmp_get_path(mi->path_name); + fbi->path = mmp_get_path(path_name); if (!fbi->path) { - dev_err(&pdev->dev, "can't get the path %s\n", mi->path_name); - ret = -EINVAL; + dev_err(&pdev->dev, "can't get the path %s\n", path_name); goto failed_destroy_mutex; } dev_info(fbi->dev, "path %s get\n", fbi->path->name); /* get overlay */ - fbi->overlay = mmp_path_get_overlay(fbi->path, mi->overlay_id); - if (!fbi->overlay) { - ret = -EINVAL; + fbi->overlay = mmp_path_get_overlay(fbi->path, overlay_id); + if (!fbi->overlay) goto failed_destroy_mutex; - } + /* set fetch used */ - mmp_overlay_set_fetch(fbi->overlay, mi->dmafetch_id); + mmp_overlay_set_fetch(fbi->overlay, dmafetch_id); modes_num = modes_setup(fbi); if (modes_num < 0) { @@ -679,6 +711,7 @@ static struct platform_driver mmpfb_driver = { .driver = { .name = "mmp-fb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mmp_fb_dt_match), }, .probe = mmpfb_probe, }; diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c index 8621a9f..19d68bc 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.c +++ b/drivers/video/mmp/hw/mmp_ctrl.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "mmp_ctrl.h" @@ -396,26 +398,57 @@ static void path_set_default(struct mmp_path *path) writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); } -static int path_init(struct mmphw_path_plat *path_plat, - struct mmp_mach_path_config *config) +static int path_init(struct mmphw_path_plat *path_plat, void *arg) { struct mmphw_ctrl *ctrl = path_plat->ctrl; struct mmp_path_info *path_info; struct mmp_path *path = NULL; - - dev_info(ctrl->dev, "%s: %s\n", __func__, config->name); +#ifdef CONFIG_OF + struct device_node *path_np = arg; +#else + struct mmp_mach_path_config *config = arg; +#endif /* init driver data */ path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL); if (!path_info) { - dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n", - __func__, config->name); - return 0; + dev_err(ctrl->dev, "%s: unable to alloc path_info\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (!path_np || of_property_read_string(path_np, "marvell,path-name", + &path_info->name) || + of_property_read_u32(path_np, "marvell,overlay-num", + &path_info->output_type) || + of_property_read_u32(path_np, "marvell,output-type", + &path_info->overlay_num)) { + dev_err(ctrl->dev, "%s: unable to get path setting from dt\n", + __func__); + kfree(path_info); + return -EINVAL; } + /* allow these settings not set */ + of_property_read_u32(path_np, "marvell,path-config", + &path_plat->path_config); + of_property_read_u32(path_np, "marvell,link-config", + &path_plat->link_config); + of_property_read_u32(path_np, "marvell,rbswap", + &path_plat->dsi_rbswap); +#else path_info->name = config->name; + path_info->overlay_num = config->overlay_num; + path_info->output_type = config->output_type; + path_plat->path_config = config->path_config; + path_plat->link_config = config->link_config; + path_plat->dsi_rbswap = config->dsi_rbswap; +#endif + + dev_info(ctrl->dev, "%s: %s\n", __func__, path_info->name); + path_info->id = path_plat->id; path_info->dev = ctrl->dev; - path_info->overlay_num = config->overlay_num; path_info->overlay_ops = &mmphw_overlay_ops; path_info->set_mode = path_set_mode; path_info->plat_data = path_plat; @@ -424,16 +457,13 @@ static int path_init(struct mmphw_path_plat *path_plat, path = mmp_register_path(path_info); if (!path) { kfree(path_info); - return 0; + return -EINVAL; } path_plat->path = path; - path_plat->path_config = config->path_config; - path_plat->link_config = config->link_config; - path_plat->dsi_rbswap = config->dsi_rbswap; path_set_default(path); kfree(path_info); - return 1; + return 0; } static void path_deinit(struct mmphw_path_plat *path_plat) @@ -445,13 +475,25 @@ static void path_deinit(struct mmphw_path_plat *path_plat) mmp_unregister_path(path_plat->path); } +#ifdef CONFIG_OF +static const struct of_device_id mmp_disp_dt_match[] = { + { .compatible = "marvell,mmp-disp" }, + {}, +}; +#endif + static int mmphw_probe(struct platform_device *pdev) { - struct mmp_mach_plat_info *mi; struct resource *res; - int ret, i, size, irq; + int ret, i, size, irq, path_num; + const char *clk_name, *disp_name; struct mmphw_path_plat *path_plat; struct mmphw_ctrl *ctrl = NULL; +#ifdef CONFIG_OF + struct device_node *np, *path_np = NULL; +#else + struct mmp_mach_plat_info *mi; +#endif /* get resources from platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -468,6 +510,22 @@ static int mmphw_probe(struct platform_device *pdev) goto failed; } +#ifdef CONFIG_OF + np = pdev->dev.of_node; + + if (!np || of_property_read_u32(np, + "marvell,path-num", &path_num) || + of_property_read_string(np, + "marvell,disp-name", &disp_name) || + of_property_read_string(np, + "marvell,clk-name", &clk_name) || + of_get_child_count(np) != ctrl->path_num) { + dev_err(&pdev->dev, "%s: failed to get settings from dt\n", + __func__); + ret = -EINVAL; + goto failed; + } +#else /* get configs from platform data */ mi = pdev->dev.platform_data; if (mi == NULL || !mi->path_num || !mi->paths) { @@ -476,17 +534,21 @@ static int mmphw_probe(struct platform_device *pdev) goto failed; } - /* allocate */ + disp_name = mi->name; + path_num = mi->path_num; + clk_name = mi->clk_name; +#endif + + /* allocate ctrl */ size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) * - mi->path_num; + path_num; ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (!ctrl) { ret = -ENOMEM; goto failed; } - - ctrl->name = mi->name; - ctrl->path_num = mi->path_num; + ctrl->path_num = path_num; + ctrl->name = disp_name; ctrl->dev = &pdev->dev; ctrl->irq = irq; platform_set_drvdata(pdev, ctrl); @@ -521,9 +583,9 @@ static int mmphw_probe(struct platform_device *pdev) } /* get clock */ - ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name); + ctrl->clk = devm_clk_get(ctrl->dev, clk_name); if (IS_ERR(ctrl->clk)) { - dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name); + dev_err(ctrl->dev, "unable to get clk %s\n", clk_name); ret = -ENOENT; goto failed; } @@ -539,11 +601,16 @@ static int mmphw_probe(struct platform_device *pdev) path_plat->id = i; path_plat->ctrl = ctrl; - /* path init */ - if (!path_init(path_plat, &mi->paths[i])) { - ret = -EINVAL; + /* path init from mach info or dt */ +#ifdef CONFIG_OF + path_np = of_get_next_child(np, path_np); + ret = path_init(path_plat, path_np); +#else + ret = path_init(path_plat, &mi->paths[i]); +#endif + + if (ret) goto failed_path_init; - } } #ifdef CONFIG_MMP_DISP_SPI @@ -573,6 +640,7 @@ static struct platform_driver mmphw_driver = { .driver = { .name = "mmp-disp", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mmp_disp_dt_match), }, .probe = mmphw_probe, };