From patchwork Mon Sep 18 03:21:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 814757 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tPU4nnCB"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xwWX34FKvz9ryr for ; Mon, 18 Sep 2017 13:22:10 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 814FCC21EDB; Mon, 18 Sep 2017 03:22:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 50249C21D19; Mon, 18 Sep 2017 03:21:59 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 0E3D5C21D19; Mon, 18 Sep 2017 03:21:56 +0000 (UTC) Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by lists.denx.de (Postfix) with ESMTPS id A59DBC21C62 for ; Mon, 18 Sep 2017 03:21:55 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id f84so4047568pfj.3 for ; Sun, 17 Sep 2017 20:21:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=A11LA8QqTtgJaYjcqwinjHuFwi+9Mchk01jUwBSGCio=; b=tPU4nnCBMd+1Wn0awxbvA9JbsHvmfsw+JUX0rPVdxLcPDio1c3dlkX3i/LeeWwXDrN mTY8WsM3V4Ajf10chAJTPYQWVnDewl56dIAtX6kb0exdQVhLG3nEUaOvfQHYDlLra8BC RkYIkIXgqGqC1TJs4RTnyG1ZHMCGnmY509j95+9AtCmG7mUnM1R5Om3tnIGp0cUTdDqX /SFiMpOBr7iQ5AFL+q1QLmQemarbUKVnJr8luKbqL1FuLIwTqqq0qdA8tnn/r/i1AI/V YkIYvXh2wyk+3p7kxCjnbkdlpRVGciR5uJste1J+zqXJM1aKPkK//tnHDHljgXQUBN5D CeOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=A11LA8QqTtgJaYjcqwinjHuFwi+9Mchk01jUwBSGCio=; b=WK8zTa5OlebfcRKfoWR8BnHjim/lwMpxMtQErEKfcGpaidM4gsoDWqsGH8rj05SSEb KXj1WcjPHnl+0+T4tcmpPwATqzAxTPyBahxEuMtjSiwXPIhv627rFQVSfXFKHjblNKQp exjquwh4U9bGObLPMEOOXpXXyVNGhcftA1ozqjeqhUzqEs1T8bfmdY2Da23tq27PzMcq IAnMIm01nlFGuHxi+bUAHg+SSXhyWnW+ZoKtR7QfKozX/MEFjAbCSNn9adQ72WJSekJv c9sZAkNlryLaFJVb30lK9f8YXu0G0EEi/0u+FYnjbFkWRU6vLALQK5jEDCaIYGa0srCH L+kQ== X-Gm-Message-State: AHPjjUgluLJiYXcRIRSEaf6GRwhU75sVMiUA0JrSe8ULqLg7mVn7e+PQ Jb8WveAgYi2OpO9YYrU= X-Google-Smtp-Source: ADKCNb4PJp8b/QLM0Hfj8ocirBSyfZ0RAy8c1GHbIWj7lfawSmN9pIZiL8uKUPB4l5HHByUHWiWizg== X-Received: by 10.98.34.85 with SMTP id i82mr26695405pfi.111.1505704914175; Sun, 17 Sep 2017 20:21:54 -0700 (PDT) Received: from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net. [216.71.193.140]) by smtp.gmail.com with ESMTPSA id 5sm11500606pfr.151.2017.09.17.20.21.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 20:21:53 -0700 (PDT) From: Vasily Khoruzhick To: u-boot@lists.denx.de, jernej.skrabec@siol.net, icenowy@aosc.io Date: Sun, 17 Sep 2017 20:21:41 -0700 Message-Id: <20170918032145.25349-1-anarsoul@gmail.com> X-Mailer: git-send-email 2.14.1 Subject: [U-Boot] [PATCH 1/5] dm: video: bridge: add operation to read EDID X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Bridge may have ability to read EDID from panel that is connected to it, so add an operation to read EDID. Signed-off-by: Vasily Khoruzhick --- drivers/video/bridge/video-bridge-uclass.c | 10 ++++++++++ include/video_bridge.h | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c index 07270bac9e..79facd02a6 100644 --- a/drivers/video/bridge/video-bridge-uclass.c +++ b/drivers/video/bridge/video-bridge-uclass.c @@ -8,6 +8,7 @@ #include #include #include +#include #include int video_bridge_set_backlight(struct udevice *dev, int percent) @@ -45,6 +46,15 @@ int video_bridge_check_attached(struct udevice *dev) return ops->check_attached(dev); } +int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size) +{ + struct video_bridge_ops *ops = video_bridge_get_ops(dev); + + if (!ops || !ops->read_edid) + return -ENOSYS; + return ops->read_edid(dev, buf, buf_size); +} + static int video_bridge_pre_probe(struct udevice *dev) { struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); diff --git a/include/video_bridge.h b/include/video_bridge.h index c7b8681849..0699a8dda8 100644 --- a/include/video_bridge.h +++ b/include/video_bridge.h @@ -53,6 +53,16 @@ struct video_bridge_ops { * @return 0 if OK, -ve on error */ int (*set_backlight)(struct udevice *dev, int percent); + + /** + * read_edid() - Read information from EDID + * + * @dev: Device to read from + * @buf: Buffer to read into + * @buf_size: Buffer size + * @return number of bytes read, <=0 for error + */ + int (*read_edid)(struct udevice *dev, u8 *buf, int buf_size); }; #define video_bridge_get_ops(dev) \ @@ -89,4 +99,14 @@ int video_bridge_set_active(struct udevice *dev, bool active); */ int video_bridge_check_attached(struct udevice *dev); +/** + * video_bridge_read_edid() - Read information from EDID + * + * @dev: Device to read from + * @buf: Buffer to read into + * @buf_size: Buffer size + * @return number of bytes read, <=0 for error + */ +int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size); + #endif From patchwork Mon Sep 18 03:21:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 814758 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="KMMPP6yW"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xwWXd6h1Cz9ryr for ; Mon, 18 Sep 2017 13:22:41 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id B3B5CC21EFD; Mon, 18 Sep 2017 03:22:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 297CBC21EAB; Mon, 18 Sep 2017 03:22:00 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C766AC21CB6; Mon, 18 Sep 2017 03:21:57 +0000 (UTC) Received: from mail-pf0-f196.google.com (mail-pf0-f196.google.com [209.85.192.196]) by lists.denx.de (Postfix) with ESMTPS id 72BBCC21CB6 for ; Mon, 18 Sep 2017 03:21:56 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id i23so4052793pfi.2 for ; Sun, 17 Sep 2017 20:21:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lqXjXSY7LJCWBWJVqEyc/7aMvLNhh8WoqcfKi2209yk=; b=KMMPP6yWItG218BVJw/rhClNDXQ2dTSgnEUIQBAzKuiKiSj/ZHRBTdf0yyqyfp4AO0 U4RUvpykIDiqcqER0fhyYwp/NOWx7nZcUUHJ9SVs3LNWitAVBOFoTg4/on+CWn1T7Ajw un+uBfHiXpmqb6uTZIOkoAgZDRoR2COx9QvLOqHxC+oMEb/Suf1jNyZl3Llau6BfFTmw IvIh5Cq0HUtkbQxB81n7IhrcRw6e4Egtk+wMsf/V/8+rZvZVjYQWBSXSAfvGLdAYxU8e 4b/ifj9UAlK0pKOl+u64rWQNNrxR0YTT41QpP7U2Oe6BsNwMPmRHT5kbG+6oQmI9/cFS CPvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lqXjXSY7LJCWBWJVqEyc/7aMvLNhh8WoqcfKi2209yk=; b=T972qwnrNFzbFPi7vHN+lohWOWP3x1Iho3oSCQvcCplo+pltWB7kkNnu0bbHbaRizD qFWIENY5ZUWO7jVfsCnPv9/LlxVe8kBTOMfEnyFRx2UWyIiZbHVBOrCKLZEDizHvhYnP FDVbAAPrfBWDCUlPYLichKOPZ6qdoOD9EULfPxSYMQUxBrx1SWv7K0MS4EtKwWKNqYOt 0nhjZK5hum9m3jVCaGiJ42K3rklSwqU2Jdznph8EPzctEERjrhuyOxzzaFiMm4ySl7QO iHnVziBRS5EBRF9dk1bmQGO8Ik2DlGGl/98QlAnHlTgFQ+1b2LpHK3BCPdL9NFYFbhn6 Y70g== X-Gm-Message-State: AHPjjUj0kcijFo7wI4ROiIl87BPZ8wqhHy9MiIXKFIxmOzjRWYFoAGze nyyptt+4Kpw5GRaPxfk= X-Google-Smtp-Source: ADKCNb7mUor27VFKP1g0WZQmclfLg7JRoh+ycmb+3/UldKJtWoOmooOxlSC892gXgWnyqP/Q1D15zQ== X-Received: by 10.98.193.2 with SMTP id i2mr30192781pfg.207.1505704914956; Sun, 17 Sep 2017 20:21:54 -0700 (PDT) Received: from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net. [216.71.193.140]) by smtp.gmail.com with ESMTPSA id 5sm11500606pfr.151.2017.09.17.20.21.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 20:21:54 -0700 (PDT) From: Vasily Khoruzhick To: u-boot@lists.denx.de, jernej.skrabec@siol.net, icenowy@aosc.io Date: Sun, 17 Sep 2017 20:21:42 -0700 Message-Id: <20170918032145.25349-2-anarsoul@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170918032145.25349-1-anarsoul@gmail.com> References: <20170918032145.25349-1-anarsoul@gmail.com> Subject: [U-Boot] [PATCH 2/5] video: anx9804: split out registers definitions into a separate header X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This header will be used in anx6345 driver Signed-off-by: Vasily Khoruzhick --- drivers/video/anx9804.c | 54 +-------------------------- include/anx98xx-edp.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 53 deletions(-) create mode 100644 include/anx98xx-edp.h diff --git a/drivers/video/anx9804.c b/drivers/video/anx9804.c index 37ad69a039..67f7da7d18 100755 --- a/drivers/video/anx9804.c +++ b/drivers/video/anx9804.c @@ -12,61 +12,9 @@ #include #include +#include #include "anx9804.h" -/* Registers at i2c address 0x38 */ - -#define ANX9804_HDCP_CONTROL_0_REG 0x01 - -#define ANX9804_SYS_CTRL2_REG 0x81 -#define ANX9804_SYS_CTRL2_CHA_STA 0x04 - -#define ANX9804_SYS_CTRL3_REG 0x82 -#define ANX9804_SYS_CTRL3_VALID_CTRL BIT(0) -#define ANX9804_SYS_CTRL3_F_VALID BIT(1) -#define ANX9804_SYS_CTRL3_HPD_CTRL BIT(4) -#define ANX9804_SYS_CTRL3_F_HPD BIT(5) - -#define ANX9804_LINK_BW_SET_REG 0xa0 -#define ANX9804_LANE_COUNT_SET_REG 0xa1 -#define ANX9804_TRAINING_PTN_SET_REG 0xa2 -#define ANX9804_TRAINING_LANE0_SET_REG 0xa3 -#define ANX9804_TRAINING_LANE1_SET_REG 0xa4 -#define ANX9804_TRAINING_LANE2_SET_REG 0xa5 -#define ANX9804_TRAINING_LANE3_SET_REG 0xa6 - -#define ANX9804_LINK_TRAINING_CTRL_REG 0xa8 -#define ANX9804_LINK_TRAINING_CTRL_EN BIT(0) - -#define ANX9804_LINK_DEBUG_REG 0xb8 -#define ANX9804_PLL_CTRL_REG 0xc7 -#define ANX9804_ANALOG_POWER_DOWN_REG 0xc8 - -/* Registers at i2c address 0x39 */ - -#define ANX9804_DEV_IDH_REG 0x03 - -#define ANX9804_POWERD_CTRL_REG 0x05 -#define ANX9804_POWERD_AUDIO BIT(4) - -#define ANX9804_RST_CTRL_REG 0x06 - -#define ANX9804_RST_CTRL2_REG 0x07 -#define ANX9804_RST_CTRL2_AUX BIT(2) -#define ANX9804_RST_CTRL2_AC_MODE BIT(6) - -#define ANX9804_VID_CTRL1_REG 0x08 -#define ANX9804_VID_CTRL1_VID_EN BIT(7) -#define ANX9804_VID_CTRL1_EDGE BIT(0) - -#define ANX9804_VID_CTRL2_REG 0x09 -#define ANX9804_ANALOG_DEBUG_REG1 0xdc -#define ANX9804_ANALOG_DEBUG_REG3 0xde -#define ANX9804_PLL_FILTER_CTRL1 0xdf -#define ANX9804_PLL_FILTER_CTRL3 0xe1 -#define ANX9804_PLL_FILTER_CTRL 0xe2 -#define ANX9804_PLL_CTRL3 0xe6 - /** * anx9804_init() - Init anx9804 parallel lcd to edp bridge chip * diff --git a/include/anx98xx-edp.h b/include/anx98xx-edp.h new file mode 100644 index 0000000000..f7e8baa167 --- /dev/null +++ b/include/anx98xx-edp.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2015 Hans de Goede + * Copyright (C) 2017 Vasily Khoruzhick + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Registers at i2c address 0x38 */ + +#define ANX9804_HDCP_CONTROL_0_REG 0x01 + +#define ANX9804_SYS_CTRL1_REG 0x80 +#define ANX9804_SYS_CTRL1_PD_IO 0x80 +#define ANX9804_SYS_CTRL1_PD_VID 0x40 +#define ANX9804_SYS_CTRL1_PD_LINK 0x20 +#define ANX9804_SYS_CTRL1_PD_TOTAL 0x10 +#define ANX9804_SYS_CTRL1_MODE_SEL 0x08 +#define ANX9804_SYS_CTRL1_DET_STA 0x04 +#define ANX9804_SYS_CTRL1_FORCE_DET 0x02 +#define ANX9804_SYS_CTRL1_DET_CTRL 0x01 + +#define ANX9804_SYS_CTRL2_REG 0x81 +#define ANX9804_SYS_CTRL2_CHA_STA 0x04 + +#define ANX9804_SYS_CTRL3_REG 0x82 +#define ANX9804_SYS_CTRL3_VALID_CTRL BIT(0) +#define ANX9804_SYS_CTRL3_F_VALID BIT(1) +#define ANX9804_SYS_CTRL3_HPD_CTRL BIT(4) +#define ANX9804_SYS_CTRL3_F_HPD BIT(5) + +#define ANX9804_LINK_BW_SET_REG 0xa0 +#define ANX9804_LANE_COUNT_SET_REG 0xa1 +#define ANX9804_TRAINING_PTN_SET_REG 0xa2 +#define ANX9804_TRAINING_LANE0_SET_REG 0xa3 +#define ANX9804_TRAINING_LANE1_SET_REG 0xa4 +#define ANX9804_TRAINING_LANE2_SET_REG 0xa5 +#define ANX9804_TRAINING_LANE3_SET_REG 0xa6 + +#define ANX9804_LINK_TRAINING_CTRL_REG 0xa8 +#define ANX9804_LINK_TRAINING_CTRL_EN BIT(0) + +#define ANX9804_LINK_DEBUG_REG 0xb8 +#define ANX9804_PLL_CTRL_REG 0xc7 +#define ANX9804_ANALOG_POWER_DOWN_REG 0xc8 + +#define ANX9804_AUX_CH_STA 0xe0 +#define ANX9804_AUX_BUSY BIT(4) +#define ANX9804_AUX_STATUS_MASK 0x0f + +#define ANX9804_DP_AUX_RX_COMM 0xe3 +#define ANX9804_AUX_RX_COMM_I2C_DEFER BIT(3) +#define ANX9804_AUX_RX_COMM_AUX_DEFER BIT(1) + +#define ANX9804_DP_AUX_CH_CTL_1 0xe5 +#define ANX9804_AUX_LENGTH(x) (((x - 1) & 0x0f) << 4) +#define ANX9804_AUX_TX_COMM_MASK 0x0f +#define ANX9804_AUX_TX_COMM_DP_TRANSACTION BIT(3) +#define ANX9804_AUX_TX_COMM_MOT BIT(2) +#define ANX9804_AUX_TX_COMM_READ BIT(0) + +#define ANX9804_DP_AUX_ADDR_7_0 0xe6 +#define ANX9804_DP_AUX_ADDR_15_8 0xe7 +#define ANX9804_DP_AUX_ADDR_19_16 0xe8 + +#define ANX9804_DP_AUX_CH_CTL_2 0xe9 +#define ANX9804_ADDR_ONLY BIT(1) +#define ANX9804_AUX_EN BIT(0) + +#define ANX9804_BUF_DATA_0 0xf0 + +/* Registers at i2c address 0x39 */ + +#define ANX9804_DEV_IDH_REG 0x03 + +#define ANX9804_POWERD_CTRL_REG 0x05 +#define ANX9804_POWERD_AUDIO BIT(4) + +#define ANX9804_RST_CTRL_REG 0x06 + +#define ANX9804_RST_CTRL2_REG 0x07 +#define ANX9804_RST_CTRL2_AUX BIT(2) +#define ANX9804_RST_CTRL2_AC_MODE BIT(6) + +#define ANX9804_VID_CTRL1_REG 0x08 +#define ANX9804_VID_CTRL1_VID_EN BIT(7) +#define ANX9804_VID_CTRL1_EDGE BIT(0) + +#define ANX9804_VID_CTRL2_REG 0x09 +#define ANX9804_ANALOG_DEBUG_REG1 0xdc +#define ANX9804_ANALOG_DEBUG_REG3 0xde +#define ANX9804_PLL_FILTER_CTRL1 0xdf +#define ANX9804_PLL_FILTER_CTRL3 0xe1 +#define ANX9804_PLL_FILTER_CTRL 0xe2 +#define ANX9804_PLL_CTRL3 0xe6 + +#define ANX9804_DP_INT_STA 0xf7 +#define ANX9804_RPLY_RECEIV BIT(1) +#define ANX9804_AUX_ERR BIT(0) From patchwork Mon Sep 18 03:21:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 814759 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fqH528nZ"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xwWYF6LqHz9ryr for ; Mon, 18 Sep 2017 13:23:13 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 9DB76C21ED3; Mon, 18 Sep 2017 03:22:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id EBC8DC21ED6; Mon, 18 Sep 2017 03:22:00 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 1E1EAC21D19; Mon, 18 Sep 2017 03:21:59 +0000 (UTC) Received: from mail-pg0-f66.google.com (mail-pg0-f66.google.com [74.125.83.66]) by lists.denx.de (Postfix) with ESMTPS id 98542C21C62 for ; Mon, 18 Sep 2017 03:21:57 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id m30so4578059pgn.5 for ; Sun, 17 Sep 2017 20:21:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0Mjg2iyw5iHXGShC4n6FP2c44Ww6UMK9tP1kb18oNeI=; b=fqH528nZs4J9eIrcMlENrH9WUl6m6EmGC2coL6PlgXNREbmgevV6PPNhm8tXhRnPex oZevIndcr8n/0tILY4NtCyshiBo5HaJUh/CnYQ/bNakw1mjLmp+59gxup5UX9rS9MoFC 3VjVfvDjZ9yytJF85P94jh2TO5jwOyNlLo0dBTzpXfmp1LIo37CLR7KN6+5nFBjOe4yD KW8PBX00de5baPGO1Sa/sjdhsraO2SmWgzcFIYAlDlaKjVxH9YsoIMLEoNsgNw+ZFcpH mysBbgQXQE2WtqMfSWB75YmCgDXTmAQSw9dNzR0Qr+zCXeTlqDTYuiicitRvxT82F0nP SpmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0Mjg2iyw5iHXGShC4n6FP2c44Ww6UMK9tP1kb18oNeI=; b=baSr1bW4Cx3NibTmsqR+iNhrKwnqktllSUvtueIqSh4l+A0hsiY/1waZSqsvQ2a81v 6ydbw3AlcwxWwxPh3gG51lrWMj6J7/XUgEher8DMBGzPd/RqKcpH+hhY8/+vYi6HFAl1 HkJq25dGzMmnFKFCyD41mLA8kF9RpCVeW+gu3ZLn8VWck2rmO7UMO1EJKqftorNXY5QA tZq+HBw+nE/bzZIHFJtCPKjvi99UlKDO25gcuiluqdaQgyZn0aHz5zMc2cmWaqDSMCuL 1swjMNcIXaHdL1hGCQNJpfRDixU4JudGNXgCCYmIeXRc4VTqhcOHJ5/xuiCPex9boEQO 42Dw== X-Gm-Message-State: AHPjjUhcInPC/m2EO66xzJwz4XoCvAVajX2PVM0Nbo5lXhI6leuIc249 MXq8m+qAQvn8XqmW7gM= X-Google-Smtp-Source: ADKCNb4AWNPOWAG/EHqE2VKES2f7Tsz23iikZiEAzJ0IASjrKnSJ4D9AepR+7FwhHP3KExY2iZEoWA== X-Received: by 10.99.122.22 with SMTP id v22mr30268135pgc.394.1505704915942; Sun, 17 Sep 2017 20:21:55 -0700 (PDT) Received: from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net. [216.71.193.140]) by smtp.gmail.com with ESMTPSA id 5sm11500606pfr.151.2017.09.17.20.21.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 20:21:55 -0700 (PDT) From: Vasily Khoruzhick To: u-boot@lists.denx.de, jernej.skrabec@siol.net, icenowy@aosc.io Date: Sun, 17 Sep 2017 20:21:43 -0700 Message-Id: <20170918032145.25349-3-anarsoul@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170918032145.25349-1-anarsoul@gmail.com> References: <20170918032145.25349-1-anarsoul@gmail.com> Subject: [U-Boot] [PATCH 3/5] video: add anx6345 DM driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This is a eDP bridge similar to ANX9804, it allows to connect eDP panels to the chips that can output only parallel signal Signed-off-by: Vasily Khoruzhick --- drivers/video/bridge/Kconfig | 8 + drivers/video/bridge/Makefile | 1 + drivers/video/bridge/anx6345.c | 419 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 428 insertions(+) create mode 100644 drivers/video/bridge/anx6345.c diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 2a3b6c4bee..765f7380b8 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -25,3 +25,11 @@ config VIDEO_BRIDGE_NXP_PTN3460 signalling) converter. It enables an LVDS LCD panel to be connected to an eDP output device such as an SoC that lacks LVDS capability, or where LVDS requires too many signals to route on the PCB. + +config VIDEO_BRIDGE_ANALOGIX_ANX6345 + bool "Support Analogix ANX6345 RGB->DP bridge" + depends on VIDEO_BRIDGE + select DM_I2C + help + The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD + panel to be connected to an parallel LCD interface. diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index ce731fa4ca..2a746c6f8b 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o +obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o diff --git a/drivers/video/bridge/anx6345.c b/drivers/video/bridge/anx6345.c new file mode 100644 index 0000000000..6bac9a51a9 --- /dev/null +++ b/drivers/video/bridge/anx6345.c @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2017 Vasily Khoruzhick + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DP_MAX_LINK_RATE 0x001 +#define DP_MAX_LANE_COUNT 0x002 +#define DP_MAX_LANE_COUNT_MASK 0x1f + +DECLARE_GLOBAL_DATA_PTR; + +struct anx6345_priv { + u8 edid[EDID_SIZE]; +}; + +static int anx6345_write(struct udevice *dev, unsigned addr_off, + unsigned char reg_addr, unsigned char value) +{ + uint8_t buf[2]; + struct i2c_msg msg; + int ret; + + msg.addr = addr_off; + msg.flags = 0; + buf[0] = reg_addr; + buf[1] = value; + msg.buf = buf; + msg.len = 2; + ret = dm_i2c_xfer(dev, &msg, 1); + if (ret) { + debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n", + __func__, reg_addr, value, ret); + return ret; + } + + return 0; +} + +static int anx6345_read(struct udevice *dev, unsigned addr_off, + unsigned char reg_addr, unsigned char *value) +{ + uint8_t addr, val; + struct i2c_msg msg[2]; + int ret; + + msg[0].addr = addr_off; + msg[0].flags = 0; + addr = reg_addr; + msg[0].buf = &addr; + msg[0].len = 1; + msg[1].addr = addr_off; + msg[1].flags = I2C_M_RD; + msg[1].buf = &val; + msg[1].len = 1; + ret = dm_i2c_xfer(dev, msg, 2); + if (ret) { + debug("%s: read failed, reg=%.2x, value=%p, ret=%d\n", + __func__, (int)reg_addr, value, ret); + return ret; + } + *value = val; + + return 0; +} + +static int anx6345_write_r0(struct udevice *dev, unsigned char reg_addr, + unsigned char value) +{ + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + return anx6345_write(dev, chip->chip_addr, reg_addr, value); +} + +static int anx6345_read_r0(struct udevice *dev, unsigned char reg_addr, + unsigned char *value) +{ + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + return anx6345_read(dev, chip->chip_addr, reg_addr, value); +} + +static int anx6345_write_r1(struct udevice *dev, unsigned char reg_addr, + unsigned char value) +{ + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + return anx6345_write(dev, chip->chip_addr + 1, reg_addr, value); +} + +static int anx6345_read_r1(struct udevice *dev, unsigned char reg_addr, + unsigned char *value) +{ + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + return anx6345_read(dev, chip->chip_addr + 1, reg_addr, value); +} + +static int anx6345_set_backlight(struct udevice *dev, int percent) +{ + return -ENOSYS; +} + +static int anx6345_aux_wait(struct udevice *dev) +{ + int ret = -ETIMEDOUT; + u8 v; + int retries = 1000; + do { + anx6345_read_r0(dev, ANX9804_DP_AUX_CH_CTL_2, &v); + if (!(v & ANX9804_AUX_EN)) { + ret = 0; + break; + } + udelay(100); + } while (retries--); + + if (ret) { + debug("%s: timed out waiting for AUX_EN to clear\n", __func__); + return ret; + } + + ret = -ETIMEDOUT; + retries = 1000; + do { + anx6345_read_r1(dev, ANX9804_DP_INT_STA, &v); + if (v & ANX9804_RPLY_RECEIV) { + ret = 0; + break; + } + udelay(100); + } while (retries--); + + if (ret) { + debug("%s: timed out waiting to receive reply\n", __func__); + return ret; + } + + /* Clear RPLY_RECEIV bit */ + anx6345_write_r1(dev, ANX9804_DP_INT_STA, v); + + anx6345_read_r0(dev, ANX9804_AUX_CH_STA, &v); + if ((v & ANX9804_AUX_STATUS_MASK) != 0) { + debug("AUX status: %d\n", v & ANX9804_AUX_STATUS_MASK); + ret = -EIO; + } + + return ret; +} + +static void anx6345_aux_addr(struct udevice *dev, u32 addr) +{ + u8 val; + + val = addr & 0xff; + anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_7_0, val); + val = (addr >> 8) & 0xff; + anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_15_8, val); + val = (addr >> 16) & 0x0f; + anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_19_16, val); +} + +static int anx6345_aux_transfer(struct udevice *dev, u8 req, u32 addr, u8 *buf, size_t len) +{ + int i, ret; + u8 ctrl1 = req; + u8 ctrl2 = ANX9804_AUX_EN; + + if (len > 16) + return -E2BIG; + + if (len) + ctrl1 |= ANX9804_AUX_LENGTH(len); + else + ctrl2 |= ANX9804_ADDR_ONLY; + + if (len && !(req & ANX9804_AUX_TX_COMM_READ)) { + for (i = 0; i < len; i++) + anx6345_write_r0(dev, ANX9804_BUF_DATA_0 + i, buf[i]); + } + + anx6345_aux_addr(dev, addr); + anx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_1, ctrl1); + anx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_2, ctrl2); + ret = anx6345_aux_wait(dev); + if (ret) { + debug("AUX transaction timed out\n"); + return ret; + } + + if (len && (req & ANX9804_AUX_TX_COMM_READ)) { + for (i = 0; i < len; i++) + anx6345_read_r0(dev, ANX9804_BUF_DATA_0 + i, &buf[i]); + } + + return 0; + +} + +static int anx6345_read_aux_i2c(struct udevice *dev, u8 chip_addr, + u8 offset, + size_t count, + u8 *buf) +{ + int i, ret; + size_t cur_cnt; + u8 cur_offset; + for (i = 0; i < count; i += 16) { + cur_cnt = (count - i) > 16 ? 16 : count - i; + cur_offset = offset + i; + ret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_MOT, + chip_addr, &cur_offset, 1); + if (ret) { + debug("%s: failed to set i2c offset: %d\n", __func__, ret); + return ret; + } + ret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_READ, + chip_addr, buf + i, cur_cnt); + if (ret) { + debug("%s: failed to read from i2c device: %d\n", __func__, ret); + return ret; + } + } + + return 0; +} + +static int anx6345_read_dpcd(struct udevice *dev, u32 reg, u8 *val) +{ + int ret; + + ret = anx6345_aux_transfer(dev, + ANX9804_AUX_TX_COMM_READ | + ANX9804_AUX_TX_COMM_DP_TRANSACTION, + reg, val, 1); + if (ret) { + debug ("Failed to read DPCD\n"); + return ret; + } + + return 0; +} + +static int anx6345_read_edid(struct udevice *dev, u8 *buf, int size) +{ + struct anx6345_priv *priv = dev_get_priv(dev); + + if (size > EDID_SIZE) + size = EDID_SIZE; + memcpy(buf, priv->edid, size); + + return size; +} + +static int anx6345_attach(struct udevice *dev) +{ + /* No-op */ + return 0; +} + +static int anx6345_enable(struct udevice *dev) +{ + u8 chipid, colordepth, lanes, data_rate, c; + int ret, i, bpp; + struct display_timing timing; + struct anx6345_priv *priv = dev_get_priv(dev); + + /* Deassert reset and enable power */ + ret = video_bridge_set_active(dev, true); + if (ret) + return ret; + + /* Reset */ + anx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 1); + mdelay(100); + anx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 0); + + /* Write 0 to the powerdown reg (powerup everything) */ + anx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, 0); + + ret = anx6345_read_r1(dev, ANX9804_DEV_IDH_REG, &chipid); + if (ret) + debug("%s: read id failed: %d\n", __func__, ret); + + switch (chipid) { + case 0x63: + debug("ANX63xx detected.\n"); + break; + default: + debug("Error anx6345 chipid mismatch: %.2x\n", (int)chipid); + return -ENODEV; + } + + for (i = 0; i < 100; i++) { + anx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c); + anx6345_write_r0(dev, ANX9804_SYS_CTRL2_REG, c); + anx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c); + if ((c & ANX9804_SYS_CTRL2_CHA_STA) == 0) + break; + + mdelay(5); + } + if (i == 100) + debug("Error anx6345 clock is not stable\n"); + + /* Set a bunch of analog related register values */ + anx6345_write_r0(dev, ANX9804_PLL_CTRL_REG, 0x00); + anx6345_write_r1(dev, ANX9804_ANALOG_DEBUG_REG1, 0x70); + anx6345_write_r0(dev, ANX9804_LINK_DEBUG_REG, 0x30); + + /* Force HPD */ + anx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG, + ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL); + + /* Power up and configure lanes */ + anx6345_write_r0(dev, ANX9804_ANALOG_POWER_DOWN_REG, 0x00); + anx6345_write_r0(dev, ANX9804_TRAINING_LANE0_SET_REG, 0x00); + anx6345_write_r0(dev, ANX9804_TRAINING_LANE1_SET_REG, 0x00); + anx6345_write_r0(dev, ANX9804_TRAINING_LANE2_SET_REG, 0x00); + anx6345_write_r0(dev, ANX9804_TRAINING_LANE3_SET_REG, 0x00); + + /* Reset AUX CH */ + anx6345_write_r1(dev, ANX9804_RST_CTRL2_REG, + ANX9804_RST_CTRL2_AUX); + anx6345_write_r1(dev, ANX9804_RST_CTRL2_REG, 0); + + /* Powerdown audio and some other unused bits */ + anx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, ANX9804_POWERD_AUDIO); + anx6345_write_r0(dev, ANX9804_HDCP_CONTROL_0_REG, 0x00); + anx6345_write_r0(dev, 0xa7, 0x00); + + anx6345_read_aux_i2c(dev, 0x50, 0x0, EDID_SIZE, priv->edid); + if (edid_get_timing(priv->edid, EDID_SIZE, &timing, &bpp) != 0) { + debug("Failed to parse EDID\n"); + return -EIO; + } + debug("%s: panel found: %dx%d, bpp %d\n", __func__, + timing.hactive.typ, timing.vactive.typ, + bpp); + if (bpp == 6) + colordepth = 0x00; /* 6 bit */ + else + colordepth = 0x10; /* 8 bit */ + anx6345_write_r1(dev, ANX9804_VID_CTRL2_REG, colordepth); + + if (anx6345_read_dpcd(dev, DP_MAX_LINK_RATE, &data_rate)) { + debug("%s: Failed to DP_MAX_LINK_RATE\n", __func__); + return -EIO; + } + debug("%s: data_rate: %d\n", __func__, (int)data_rate); + if (anx6345_read_dpcd(dev, DP_MAX_LANE_COUNT, &lanes)) { + debug("%s: Failed to read DP_MAX_LANE_COUNT\n", __func__); + return -EIO; + } + lanes &= DP_MAX_LANE_COUNT_MASK; + debug("%s: lanes: %d\n", __func__, (int)lanes); + + /* Set data-rate / lanes */ + anx6345_write_r0(dev, ANX9804_LINK_BW_SET_REG, data_rate); + anx6345_write_r0(dev, ANX9804_LANE_COUNT_SET_REG, lanes); + + /* Link training */ + anx6345_write_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG, + ANX9804_LINK_TRAINING_CTRL_EN); + mdelay(5); + for (i = 0; i < 100; i++) { + anx6345_read_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG, &c); + if ((chipid == 0x63) && (c & 0x80) == 0) + break; + + mdelay(5); + } + if(i == 100) { + debug("Error anx6345 link training timeout\n"); + return -ENODEV; + } + + /* Enable */ + anx6345_write_r1(dev, ANX9804_VID_CTRL1_REG, + ANX9804_VID_CTRL1_VID_EN | ANX9804_VID_CTRL1_EDGE); + /* Force stream valid */ + anx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG, + ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL | + ANX9804_SYS_CTRL3_F_VALID | ANX9804_SYS_CTRL3_VALID_CTRL); + + return 0; +} + +static int anx6345_probe(struct udevice *dev) +{ + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; + + return anx6345_enable(dev); +} + +struct video_bridge_ops anx6345_ops = { + .attach = anx6345_attach, + .set_backlight = anx6345_set_backlight, + .read_edid = anx6345_read_edid, +}; + +static const struct udevice_id anx6345_ids[] = { + { .compatible = "analogix,anx6345", }, + { } +}; + +U_BOOT_DRIVER(analogix_anx6345) = { + .name = "analogix_anx6345", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = anx6345_ids, + .probe = anx6345_probe, + .ops = &anx6345_ops, + .priv_auto_alloc_size = sizeof(struct anx6345_priv), +}; From patchwork Mon Sep 18 03:21:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 814760 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bL4/38F5"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xwWZX48tQz9ryr for ; Mon, 18 Sep 2017 13:24:20 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 48261C21ED4; Mon, 18 Sep 2017 03:23:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9A83BC21F00; Mon, 18 Sep 2017 03:22:09 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 620CFC21EE9; Mon, 18 Sep 2017 03:22:03 +0000 (UTC) Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by lists.denx.de (Postfix) with ESMTPS id 066C9C21CB6 for ; Mon, 18 Sep 2017 03:21:59 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id g65so4051106pfe.1 for ; Sun, 17 Sep 2017 20:21:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uIzWNTwQ4KzrRJJZNIaW6+s5byMYxEBGOJFBOfWqBxE=; b=bL4/38F5W9WQr8oZp/o212T/dlHSfqFDO26snYj7x1aBH+2VqHD0iv4Sx2WQUlOiFu CabbjYedrD4blNs582u41J9GfhuBtf5azIZHyjxVd1ocd+0T2+3VNG0wLMbIJTsQJ6aT Okopq53HYWicpTd+HW076GoOHXJNajq7BRpPBSDWTIhZLGbS8UUpUZGP5ephdiFop65/ FqEfimrJoOcBlrKGzM7Q5Or74bwnUrtRWxutoZmrGTsEY/Tmut+LTOjEZsrjlQbtDCFg BObfyJlAoHiaQ0mh8bqo55xdW3ZuNtVkAdSj1kgRGcp7OCggI8S1Gc3A+NixbWPQaFUo G8SA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uIzWNTwQ4KzrRJJZNIaW6+s5byMYxEBGOJFBOfWqBxE=; b=W+wfU6R9f8IdVdBJM2bjmk0tnyLetxEtRXrpxtElxQCMRotZY551u4UMIPVYkhtMjZ JIWVw10C0eSQpEhLZI+UTyDQ4DwVfUfNuTJBhdOUnH13rPdd5Fik1iLTWTzn8rUnDScf E4TocpJPgvjVlUfVfNmDOgK7EYsKeQCA3EemKGEeozvJ/KmnMvliKeWXnXF0ovlYXj7f 5rhY1fziZ7BcEXzjonzk9lsX14prC5XVz0+MghieUuECAIFA80vtRbALyvJvpnGJ6YLs L3HlEcqYIAe+f4ip5v2we4sj8giO08i4IzYTel9Hk7ryeR7Pc/RAuZAqOxixFP7c8WwY Deag== X-Gm-Message-State: AHPjjUhjDkxmQxIj1SD18qPppgZJJd8/b1CO1e4oBi/pTpCkrNSxVXa8 RH8j0TmjpVqctNk1lUg= X-Google-Smtp-Source: ADKCNb4m6ok1NFrlL4sV2YKTsz8qs7eeERqYBeKZkOSzpzDVw5l8Zf7xbnlPhyVCteyhelWu8E/F4Q== X-Received: by 10.99.95.204 with SMTP id t195mr31108472pgb.135.1505704917340; Sun, 17 Sep 2017 20:21:57 -0700 (PDT) Received: from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net. [216.71.193.140]) by smtp.gmail.com with ESMTPSA id 5sm11500606pfr.151.2017.09.17.20.21.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 20:21:56 -0700 (PDT) From: Vasily Khoruzhick To: u-boot@lists.denx.de, jernej.skrabec@siol.net, icenowy@aosc.io Date: Sun, 17 Sep 2017 20:21:44 -0700 Message-Id: <20170918032145.25349-4-anarsoul@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170918032145.25349-1-anarsoul@gmail.com> References: <20170918032145.25349-1-anarsoul@gmail.com> Subject: [U-Boot] [PATCH 4/5] sunxi: video: split out PLL code X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" It will be reused in new DM LCD driver. Signed-off-by: Vasily Khoruzhick --- arch/arm/include/asm/arch-sunxi/lcdc.h | 2 + drivers/video/sunxi/lcdc.c | 117 ++++++++++++++++++++++++++++++- drivers/video/sunxi/sunxi_display.c | 121 ++------------------------------- 3 files changed, 124 insertions(+), 116 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/lcdc.h b/arch/arm/include/asm/arch-sunxi/lcdc.h index a751698b4f..5d9253aaa5 100644 --- a/arch/arm/include/asm/arch-sunxi/lcdc.h +++ b/arch/arm/include/asm/arch-sunxi/lcdc.h @@ -124,5 +124,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc, void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc, const struct display_timing *mode, bool ext_hvsync, bool is_composite); +void lcdc_pll_set(struct sunxi_ccm_reg * const ccm, int tcon, + int dotclock, int *clk_div, int *clk_double); #endif /* _LCDC_H */ diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c index 7d215b713e..023a30cb1e 100644 --- a/drivers/video/sunxi/lcdc.c +++ b/drivers/video/sunxi/lcdc.c @@ -10,6 +10,7 @@ #include +#include #include #include @@ -100,7 +101,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc, writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) | SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v); -#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL +#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_VIDEO_DE2) writel(SUNXI_LCDC_X(mode->hsync_len.typ) | SUNXI_LCDC_Y(mode->vsync_len.typ), &lcdc->tcon0_timing_sync); @@ -207,3 +208,117 @@ void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc, SUNXI_LCDC_MUX_CTRL_SRC0(1)); #endif } + +void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock, + int *clk_div, int *clk_double) +{ + int value, n, m, min_m, max_m, diff; + int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF; + int best_double = 0; + bool use_mipi_pll = false; + + if (tcon == 0) { +#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_SUNXI_DE2) + min_m = 6; + max_m = 127; +#endif +#ifdef CONFIG_VIDEO_LCD_IF_LVDS + min_m = max_m = 7; +#endif + } else { + min_m = 1; + max_m = 15; + } + + /* + * Find the lowest divider resulting in a matching clock, if there + * is no match, pick the closest lower clock, as monitors tend to + * not sync to higher frequencies. + */ + for (m = min_m; m <= max_m; m++) { +#ifndef CONFIG_SUNXI_DE2 + n = (m * dotclock) / 3000; + + if ((n >= 9) && (n <= 127)) { + value = (3000 * n) / m; + diff = dotclock - value; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n = n; + best_double = 0; + } + } + + /* These are just duplicates */ + if (!(m & 1)) + continue; +#endif + + /* No double clock on DE2 */ + n = (m * dotclock) / 6000; + if ((n >= 9) && (n <= 127)) { + value = (6000 * n) / m; + diff = dotclock - value; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n = n; + best_double = 1; + } + } + } + +#ifdef CONFIG_MACH_SUN6I + /* + * Use the MIPI pll if we've been unable to find any matching setting + * for PLL3, this happens with high dotclocks because of min_m = 6. + */ + if (tcon == 0 && best_n == 0) { + use_mipi_pll = true; + best_m = 6; /* Minimum m for tcon0 */ + } + + if (use_mipi_pll) { + clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */ + clock_set_mipi_pll(best_m * dotclock * 1000); + debug("dotclock: %dkHz = %dkHz via mipi pll\n", + dotclock, clock_get_mipi_pll() / best_m / 1000); + } else +#endif + { + clock_set_pll3(best_n * 3000000); + debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n", + dotclock, + (best_double + 1) * clock_get_pll3() / best_m / 1000, + best_double + 1, best_n, best_m); + } + + if (tcon == 0) { + u32 pll; + + if (use_mipi_pll) + pll = CCM_LCD_CH0_CTRL_MIPI_PLL; + else if (best_double) + pll = CCM_LCD_CH0_CTRL_PLL3_2X; + else + pll = CCM_LCD_CH0_CTRL_PLL3; + + writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll, + &ccm->lcd0_clk_cfg); + } +#ifndef CONFIG_SUNXI_DE2 + else { + writel(CCM_LCD_CH1_CTRL_GATE | + (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X : + CCM_LCD_CH1_CTRL_PLL3) | + CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg); + if (sunxi_is_composite()) + setbits_le32(&ccm->lcd0_ch1_clk_cfg, + CCM_LCD_CH1_CTRL_HALF_SCLK1); + } +#endif + + *clk_div = best_m; + *clk_double = best_double; +} diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index de768ba94a..f3db125305 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -515,119 +515,6 @@ static void sunxi_composer_enable(void) setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START); } -/* - * LCDC, what allwinner calls a CRTC, so timing controller and serializer. - */ -static void sunxi_lcdc_pll_set(int tcon, int dotclock, - int *clk_div, int *clk_double) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int value, n, m, min_m, max_m, diff; - int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF; - int best_double = 0; - bool use_mipi_pll = false; - - if (tcon == 0) { -#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL - min_m = 6; - max_m = 127; -#endif -#ifdef CONFIG_VIDEO_LCD_IF_LVDS - min_m = max_m = 7; -#endif - } else { - min_m = 1; - max_m = 15; - } - - /* - * Find the lowest divider resulting in a matching clock, if there - * is no match, pick the closest lower clock, as monitors tend to - * not sync to higher frequencies. - */ - for (m = min_m; m <= max_m; m++) { - n = (m * dotclock) / 3000; - - if ((n >= 9) && (n <= 127)) { - value = (3000 * n) / m; - diff = dotclock - value; - if (diff < best_diff) { - best_diff = diff; - best_m = m; - best_n = n; - best_double = 0; - } - } - - /* These are just duplicates */ - if (!(m & 1)) - continue; - - n = (m * dotclock) / 6000; - if ((n >= 9) && (n <= 127)) { - value = (6000 * n) / m; - diff = dotclock - value; - if (diff < best_diff) { - best_diff = diff; - best_m = m; - best_n = n; - best_double = 1; - } - } - } - -#ifdef CONFIG_MACH_SUN6I - /* - * Use the MIPI pll if we've been unable to find any matching setting - * for PLL3, this happens with high dotclocks because of min_m = 6. - */ - if (tcon == 0 && best_n == 0) { - use_mipi_pll = true; - best_m = 6; /* Minimum m for tcon0 */ - } - - if (use_mipi_pll) { - clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */ - clock_set_mipi_pll(best_m * dotclock * 1000); - debug("dotclock: %dkHz = %dkHz via mipi pll\n", - dotclock, clock_get_mipi_pll() / best_m / 1000); - } else -#endif - { - clock_set_pll3(best_n * 3000000); - debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n", - dotclock, - (best_double + 1) * clock_get_pll3() / best_m / 1000, - best_double + 1, best_n, best_m); - } - - if (tcon == 0) { - u32 pll; - - if (use_mipi_pll) - pll = CCM_LCD_CH0_CTRL_MIPI_PLL; - else if (best_double) - pll = CCM_LCD_CH0_CTRL_PLL3_2X; - else - pll = CCM_LCD_CH0_CTRL_PLL3; - - writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll, - &ccm->lcd0_ch0_clk_cfg); - } else { - writel(CCM_LCD_CH1_CTRL_GATE | - (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X : - CCM_LCD_CH1_CTRL_PLL3) | - CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg); - if (sunxi_is_composite()) - setbits_le32(&ccm->lcd0_ch1_clk_cfg, - CCM_LCD_CH1_CTRL_HALF_SCLK1); - } - - *clk_div = best_m; - *clk_double = best_double; -} - static void sunxi_lcdc_init(void) { struct sunxi_ccm_reg * const ccm = @@ -754,6 +641,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, { struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int clk_div, clk_double, pin; struct display_timing timing; @@ -773,7 +662,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, #endif } - sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double); + lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double); sunxi_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac, @@ -787,6 +676,8 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, { struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct display_timing timing; sunxi_ctfb_mode_to_display_timing(mode, &timing); @@ -798,7 +689,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0); } - sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double); + lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double); } #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */ From patchwork Mon Sep 18 03:21:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 814761 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ifRlT8rH"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xwWb416k3z9ryr for ; Mon, 18 Sep 2017 13:24:48 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E7EAAC21ED8; Mon, 18 Sep 2017 03:23:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 640AFC21F03; Mon, 18 Sep 2017 03:22:11 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5061CC21EF7; Mon, 18 Sep 2017 03:22:05 +0000 (UTC) Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by lists.denx.de (Postfix) with ESMTPS id D23CCC21DE4 for ; Mon, 18 Sep 2017 03:21:59 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id v82so4585832pgb.1 for ; Sun, 17 Sep 2017 20:21:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SCXf1WleS9jSZ8TAgh98vTEnRQoHhnwZtukQd4s2XXI=; b=ifRlT8rHXLtyggxhxFsfgzaWxDb/YdNqJjjZ7I39QuKwdIK1yEIeaPbFTYpdlr+oIS zVvLTgUB+du+nFzQ8vANxkErr/Y7Kh5SmROue7dMGWDs5j/coRPnMV2a7LDrj9edWtQ+ ZLSHHwUYH2Tzb/2Sy7WURj7F5KiqPW94HSuTeMBo1n+FX3kQvwYUtQuzv2RkcobVKm7s ThSUCDHD0OO7U5mZF+Do71xNAw5r2zc3x7MfAg3XnGBaEdPfQHV6oM871jqRq8tmREnQ NYGJnRh40963F6tdN3DtO1GMDCTu44PVkg+t3L4y02jZdUnAym3IGGzLfDr9q9wdAxGC t31A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SCXf1WleS9jSZ8TAgh98vTEnRQoHhnwZtukQd4s2XXI=; b=pJnnhYCmUjNCCCTL7lXVEM+W7zmqVg2LK66AxKTKVUBZL73mpvPgwC75NgH4PWDkQg 3d+IHJ75ACgMB8VtHCxYR9U610CydH33Zr+YO/7z4OqoYPwXfi4iLHyztkDmG8E+TiEa npHXWZMSRFKHN89LeH9tx7vAtrszUCd8IEExZIIJGYEs91X0lY3IbG0n7+9D8uBvqyvo fuaAoJhcaST4uut2IWWcFszObxzj9rt20x5DZ5/QdvREIgEmJ2Bcdc3BQlcCi61Sn1y/ MBkDxEOKTgMjoHBPfCEWFSxaWoG2uXhGzBJzy9wa0Ab4jgsjIohwCFMfMUhmVm6Pq6Es pSMQ== X-Gm-Message-State: AHPjjUieXHYtN0d8ihcoBHbZ+xhl4YqIA1vy74uUI5Qin256z2k1xpX6 1txArpIQW9r137hwaf0= X-Google-Smtp-Source: ADKCNb5+5xeZhm1CtD+efXLo7TlIrCKJ9N0v3yqTfkvf/H1U/9y1IDoRrDZcISLfJdsEleY2DVB4OA== X-Received: by 10.99.95.131 with SMTP id t125mr30985851pgb.172.1505704918329; Sun, 17 Sep 2017 20:21:58 -0700 (PDT) Received: from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net. [216.71.193.140]) by smtp.gmail.com with ESMTPSA id 5sm11500606pfr.151.2017.09.17.20.21.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 20:21:57 -0700 (PDT) From: Vasily Khoruzhick To: u-boot@lists.denx.de, jernej.skrabec@siol.net, icenowy@aosc.io Date: Sun, 17 Sep 2017 20:21:45 -0700 Message-Id: <20170918032145.25349-5-anarsoul@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170918032145.25349-1-anarsoul@gmail.com> References: <20170918032145.25349-1-anarsoul@gmail.com> Subject: [U-Boot] [PATCH 5/5] sunxi: video: add LCD support to DE2 driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Extend DE2 driver with LCD support Signed-off-by: Vasily Khoruzhick --- arch/arm/mach-sunxi/Kconfig | 2 +- drivers/video/sunxi/Makefile | 2 +- drivers/video/sunxi/sunxi_de2.c | 17 +++++ drivers/video/sunxi/sunxi_lcd.c | 142 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 drivers/video/sunxi/sunxi_lcd.c diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 2309f59999..06d697e3a7 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -680,7 +680,7 @@ config VIDEO_LCD_MODE config VIDEO_LCD_DCLK_PHASE int "LCD panel display clock phase" - depends on VIDEO + depends on VIDEO || DM_VIDEO default 1 ---help--- Select LCD panel display clock phase shift, range 0-3. diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile index 0d64c2021f..8c91766c24 100644 --- a/drivers/video/sunxi/Makefile +++ b/drivers/video/sunxi/Makefile @@ -6,4 +6,4 @@ # obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o tve_common.o ../videomodes.o -obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o +obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o sunxi_lcd.o diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c index ee67764ac5..a838bbacd1 100644 --- a/drivers/video/sunxi/sunxi_de2.c +++ b/drivers/video/sunxi/sunxi_de2.c @@ -232,6 +232,23 @@ static int sunxi_de2_probe(struct udevice *dev) if (!(gd->flags & GD_FLG_RELOC)) return 0; + ret = uclass_find_device_by_name(UCLASS_DISPLAY, + "sunxi_lcd", &disp); + if (!ret) { + int mux; + + mux = 0; + + ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux, + false); + if (!ret) { + video_set_flush_dcache(dev, 1); + return 0; + } + } + + debug("%s: lcd display not found (ret=%d)\n", __func__, ret); + ret = uclass_find_device_by_name(UCLASS_DISPLAY, "sunxi_dw_hdmi", &disp); if (!ret) { diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c new file mode 100644 index 0000000000..154eb5835e --- /dev/null +++ b/drivers/video/sunxi/sunxi_lcd.c @@ -0,0 +1,142 @@ +/* + * Allwinner LCD driver + * + * (C) Copyright 2017 Vasily Khoruzhick + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sunxi_lcd_priv { + struct display_timing timing; + int panel_bpp; +}; + +static void sunxi_lcdc_config_pinmux(void) +{ + int pin; + for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(21); pin++) { + sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0); + sunxi_gpio_set_drv(pin, 3); + } +} + +static int sunxi_lcd_enable(struct udevice *dev, int bpp, + const struct display_timing *edid) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_lcdc_reg * const lcdc = + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + struct sunxi_lcd_priv *priv = dev_get_priv(dev); + struct udevice *backlight; + int clk_div, clk_double, ret; + + /* Reset off */ + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0); + + /* Clock on */ + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0); + + lcdc_init(lcdc); + sunxi_lcdc_config_pinmux(); + lcdc_pll_set(ccm, 0, edid->pixelclock.typ / 1000, + &clk_div, &clk_double); + lcdc_tcon0_mode_set(lcdc, edid, clk_div, false, + priv->panel_bpp, CONFIG_VIDEO_LCD_DCLK_PHASE); + lcdc_enable(lcdc, priv->panel_bpp); + + ret = uclass_get_device(UCLASS_PANEL_BACKLIGHT, 0, &backlight); + if (!ret) + backlight_enable(backlight); + + return 0; +} + +static int sunxi_lcd_read_timing(struct udevice *dev, + struct display_timing *timing) +{ + struct sunxi_lcd_priv *priv = dev_get_priv(dev); + memcpy(timing, &priv->timing, sizeof(struct display_timing)); + + return 0; +} + +static int sunxi_lcd_probe(struct udevice *dev) +{ + struct udevice *cdev; + struct sunxi_lcd_priv *priv = dev_get_priv(dev); + int ret; + + /* make sure that clock is active */ + clock_set_pll10(432000000); + +#ifdef CONFIG_VIDEO_BRIDGE + /* Try to get timings from bridge first */ + ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &cdev); + if (!ret) { + u8 edid[EDID_SIZE]; + int channel_bpp; + + ret = video_bridge_attach(cdev); + if (ret) { + debug("video bridge attach failed: %d\n", ret); + return ret; + } + ret = video_bridge_read_edid(cdev, edid, EDID_SIZE); + if (ret <= 0) { + debug("video bridge failed to read edid: %d\n", ret); + return ret ? ret : -EIO; + } + ret = edid_get_timing(edid, ret, &priv->timing, &channel_bpp); + priv->panel_bpp = channel_bpp * 3; + return ret; + } + debug("video bridge not found: %d\n", ret); +#endif + /* Fallback to timings from DT if there's no bridge */ + ret = uclass_get_device(UCLASS_PANEL, 0, &cdev); + if (ret) { + debug("video panel not found: %d\n", ret); + return ret; + } + + if (fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(cdev), + 0, &priv->timing)) { + debug("%s: Failed to decode display timing\n", __func__); + return -EINVAL; + } + priv->panel_bpp = 16; + + return 0; +} + +static const struct dm_display_ops sunxi_lcd_ops = { + .read_timing = sunxi_lcd_read_timing, + .enable = sunxi_lcd_enable, +}; + +U_BOOT_DRIVER(sunxi_lcd) = { + .name = "sunxi_lcd", + .id = UCLASS_DISPLAY, + .ops = &sunxi_lcd_ops, + .probe = sunxi_lcd_probe, + .priv_auto_alloc_size = sizeof(struct sunxi_lcd_priv), +}; + +#ifdef CONFIG_MACH_SUN50I +U_BOOT_DEVICE(sunxi_lcd) = { + .name = "sunxi_lcd" +}; +#endif