From patchwork Tue Oct 28 00:01:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 5167501 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id EE1D39F349 for ; Tue, 28 Oct 2014 00:07:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DA48820211 for ; Tue, 28 Oct 2014 00:06:59 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 73E50201DD for ; Tue, 28 Oct 2014 00:06:58 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 8E63C26155D; Tue, 28 Oct 2014 01:06:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 62CF22619E9; Tue, 28 Oct 2014 01:03:40 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C0FD3261A1D; Tue, 28 Oct 2014 01:03:38 +0100 (CET) Received: from mail-wi0-f179.google.com (mail-wi0-f179.google.com [209.85.212.179]) by alsa0.perex.cz (Postfix) with ESMTP id A2EB2261558 for ; Tue, 28 Oct 2014 01:02:39 +0100 (CET) Received: by mail-wi0-f179.google.com with SMTP id h11so85076wiw.6 for ; Mon, 27 Oct 2014 17:02:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bDSKY+C73nKv4e3x3Sf/jgoWykeELNQtejMb+SABx90=; b=lq++5MyGVQziBhz4x9RMy7J3W/G1Oz3Jd5aSb3AXKccYSTIZ62PV6xNBISq3GStRL/ 5hOFK6xDObWQjCOoarBBnOHlBgAIS5kczX4nCjtn0sr82QBGHPtJbaPqTAVxz4/+h3f0 I22IpbFYh7FJQozD/4tk633APRzzDpdQqwLZi0gYsS8xjhp233hEQoWHHcT0kKgbHBRV XCmyk0ieHzukCobUPtyvs6D1pCQeognsLUzHmjS5kk3Uiu2bIVjroPMyRlGIrUk6k9l4 /hppawxmnVhT+pZkDaTqwcTikR0WOUpWmbby7ZfzbYGDyrnHlgSFoJlFjlLynwCPQ8/+ 2MfA== X-Received: by 10.194.90.15 with SMTP id bs15mr25162947wjb.47.1414454559311; Mon, 27 Oct 2014 17:02:39 -0700 (PDT) Received: from fangorn.rup.mentorg.com (nat-min.mentorg.com. [139.181.32.34]) by mx.google.com with ESMTPSA id fq1sm13495340wib.12.2014.10.27.17.02.36 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 27 Oct 2014 17:02:38 -0700 (PDT) From: Dmitry Eremin-Solenikov To: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, linux-input@vger.kernel.org, linux-leds@vger.kernel.org, linux-spi@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org Date: Tue, 28 Oct 2014 03:01:59 +0300 Message-Id: <1414454528-24240-7-git-send-email-dbaryshkov@gmail.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1414454528-24240-1-git-send-email-dbaryshkov@gmail.com> References: <1414454528-24240-1-git-send-email-dbaryshkov@gmail.com> Cc: Alexandre Courbot , Bryan Wu , Russell King , Samuel Ortiz , Lee Jones , Linus Walleij , Dmitry Torokhov , Liam Girdwood , Haojian Zhuang , Mark Brown , Andrea Adami , Jingoo Han , Richard Purdie , Robert Jarzmik , Daniel Mack Subject: [alsa-devel] [PATCH 06/15] video: lcd: add LoCoMo LCD driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP LoCoMo has some special handling for TFT screens attached to Collie and Poodle. Implement that as a separate driver. Signed-off-by: Dmitry Eremin-Solenikov --- drivers/video/backlight/Kconfig | 8 ++ drivers/video/backlight/Makefile | 1 + drivers/video/backlight/locomo_lcd.c | 224 +++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/video/backlight/locomo_lcd.c diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 03b77b33..bc5c671 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -48,6 +48,14 @@ config LCD_LMS283GF05 SPI driver for Samsung LMS283GF05. This provides basic support for powering the LCD up/down through a sysfs interface. +config LCD_LOCOMO + tristate "Sharp LOCOMO LCD Driver" + depends on MFD_LOCOMO + default y + help + If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to + enable the LCD driver. + config LCD_LTV350QV tristate "Samsung LTV350QV LCD Panel" depends on SPI_MASTER diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 2a61b7e..b2580e7 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_LCD_ILI922X) += ili922x.o obj-$(CONFIG_LCD_ILI9320) += ili9320.o obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o obj-$(CONFIG_LCD_LD9040) += ld9040.o +obj-$(CONFIG_LCD_LOCOMO) += locomo_lcd.o obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o diff --git a/drivers/video/backlight/locomo_lcd.c b/drivers/video/backlight/locomo_lcd.c new file mode 100644 index 0000000..245efb8 --- /dev/null +++ b/drivers/video/backlight/locomo_lcd.c @@ -0,0 +1,224 @@ +/* + * Backlight control code for Sharp Zaurus SL-5500 + * + * Copyright 2005 John Lenz + * Maintainer: Pavel Machek (unless John wants to :-) + * GPL v2 + * + * This driver assumes single CPU. That's okay, because collie is + * slightly old hardware, and no one is going to retrofit second CPU to + * old PDA. + */ + +/* LCD power functions */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct platform_device *locomolcd_dev; +static struct locomo_lcd_platform_data lcd_data; +static bool locomolcd_is_on; +static bool locomolcd_is_suspended; +static void __iomem *locomolcd_regs; +static struct lcd_device *lcd_dev; + +static struct gpio locomo_gpios[] = { + { 0, GPIOF_OUT_INIT_LOW, "LCD VSHA on" }, + { 0, GPIOF_OUT_INIT_LOW, "LCD VSHD on" }, + { 0, GPIOF_OUT_INIT_LOW, "LCD Vee on" }, + { 0, GPIOF_OUT_INIT_LOW, "LCD MOD" }, +}; + +static void locomolcd_on(void) +{ + gpio_set_value(lcd_data.gpio_lcd_vsha_on, 1); + mdelay(2); + + gpio_set_value(lcd_data.gpio_lcd_vshd_on, 1); + mdelay(2); + + locomo_m62332_senddata(locomolcd_dev->dev.parent, lcd_data.comadj, 0); + mdelay(5); + + gpio_set_value(lcd_data.gpio_lcd_vee_on, 1); + mdelay(10); + + /* TFTCRST | CPSOUT=0 | CPSEN */ + writew(0x01, locomolcd_regs + LOCOMO_TC); + + /* Set CPSD */ + writew(6, locomolcd_regs + LOCOMO_CPSD); + + /* TFTCRST | CPSOUT=0 | CPSEN */ + writew((0x04 | 0x01), locomolcd_regs + LOCOMO_TC); + mdelay(10); + + gpio_set_value(lcd_data.gpio_lcd_mod, 1); +} + +static void locomolcd_off(void) +{ + /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */ + writew(0x06, locomolcd_regs + LOCOMO_TC); + mdelay(1); + + gpio_set_value(lcd_data.gpio_lcd_vsha_on, 0); + mdelay(110); + + gpio_set_value(lcd_data.gpio_lcd_vee_on, 0); + mdelay(700); + + locomo_m62332_senddata(locomolcd_dev->dev.parent, 0, 0); + mdelay(5); + + /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */ + writew(0, locomolcd_regs + LOCOMO_TC); + gpio_set_value(lcd_data.gpio_lcd_mod, 0); + gpio_set_value(lcd_data.gpio_lcd_vshd_on, 0); +} + +int locomo_lcd_set_power(struct lcd_device *lcd, int power) +{ + dev_dbg(&lcd->dev, "LCD power %d (is %d)\n", power, locomolcd_is_on); + if (power == 0 && !locomolcd_is_on) { + locomolcd_is_on = 1; + locomolcd_on(); + } + if (power != 0 && locomolcd_is_on) { + locomolcd_is_on = 0; + locomolcd_off(); + } + return 0; +} + +static int locomo_lcd_get_power(struct lcd_device *lcd) +{ + return !locomolcd_is_on; +} + +static struct lcd_ops locomo_lcd_ops = { + .set_power = locomo_lcd_set_power, + .get_power = locomo_lcd_get_power, +}; + +#ifdef CONFIG_PM_SLEEP +static int locomolcd_suspend(struct device *dev) +{ + locomolcd_is_suspended = true; + locomolcd_off(); + + return 0; +} + +static int locomolcd_resume(struct device *dev) +{ + locomolcd_is_suspended = false; + + if (locomolcd_is_on) + locomolcd_on(); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(locomolcd_pm, locomolcd_suspend, locomolcd_resume); +#define LOCOMOLCD_PM (&locomolcd_pm) +#else +#define LOCOMOLCD_PM NULL +#endif + +static int locomolcd_probe(struct platform_device *dev) +{ + unsigned long flags; + struct resource *res; + struct locomo_lcd_platform_data *pdata; + int rc; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + locomolcd_regs = devm_ioremap_resource(&dev->dev, res); + if (!locomolcd_regs) + return -EINVAL; + + pdata = dev_get_platdata(&dev->dev); + if (!pdata) + return -EINVAL; + + lcd_data = *pdata; + + locomo_gpios[0].gpio = lcd_data.gpio_lcd_vsha_on; + locomo_gpios[1].gpio = lcd_data.gpio_lcd_vshd_on; + locomo_gpios[2].gpio = lcd_data.gpio_lcd_vee_on; + locomo_gpios[3].gpio = lcd_data.gpio_lcd_mod; + dev_info(&dev->dev, "GPIOs: %d %d %d %d\n", + locomo_gpios[0].gpio, + locomo_gpios[1].gpio, + locomo_gpios[2].gpio, + locomo_gpios[3].gpio); + + rc = gpio_request_array(locomo_gpios, ARRAY_SIZE(locomo_gpios)); + if (rc) + return rc; + + local_irq_save(flags); + locomolcd_dev = dev; + + locomolcd_is_on = 1; + if (locomolcd_is_on) + locomolcd_on(); + + local_irq_restore(flags); + + lcd_dev = lcd_device_register("locomo", &dev->dev, NULL, + &locomo_lcd_ops); + + return 0; +} + +static int locomolcd_remove(struct platform_device *dev) +{ + unsigned long flags; + + lcd_device_unregister(lcd_dev); + + local_irq_save(flags); + + locomolcd_off(); + locomolcd_dev = NULL; + + local_irq_restore(flags); + + gpio_free_array(locomo_gpios, ARRAY_SIZE(locomo_gpios)); + + return 0; +} + +static void locomolcd_shutdown(struct platform_device *dev) +{ + locomolcd_off(); +} + +static struct platform_driver locomolcd_driver = { + .driver = { + .name = "locomo-lcd", + .owner = THIS_MODULE, + .pm = LOCOMOLCD_PM, + }, + .probe = locomolcd_probe, + .remove = locomolcd_remove, + .shutdown = locomolcd_shutdown, +}; + +module_platform_driver(locomolcd_driver); + +MODULE_AUTHOR("John Lenz , Pavel Machek "); +MODULE_DESCRIPTION("Collie LCD driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:locomo-lcd");