Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.0 175 lines 4.3 kB view raw
1/* 2 * OPA362 analog video amplifier with output/power control 3 * 4 * Copyright (C) 2014 Golden Delicious Computers 5 * Author: H. Nikolaus Schaller <hns@goldelico.com> 6 * 7 * based on encoder-tfp410 8 * 9 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 10 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License version 2 as published by 14 * the Free Software Foundation. 15 */ 16 17#include <linux/gpio/consumer.h> 18#include <linux/module.h> 19#include <linux/platform_device.h> 20#include <linux/slab.h> 21 22#include "../dss/omapdss.h" 23 24struct panel_drv_data { 25 struct omap_dss_device dssdev; 26 27 struct gpio_desc *enable_gpio; 28}; 29 30#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) 31 32static int opa362_connect(struct omap_dss_device *src, 33 struct omap_dss_device *dst) 34{ 35 return omapdss_device_connect(dst->dss, dst, dst->next); 36} 37 38static void opa362_disconnect(struct omap_dss_device *src, 39 struct omap_dss_device *dst) 40{ 41 omapdss_device_disconnect(dst, dst->next); 42} 43 44static int opa362_enable(struct omap_dss_device *dssdev) 45{ 46 struct panel_drv_data *ddata = to_panel_data(dssdev); 47 struct omap_dss_device *src = dssdev->src; 48 int r; 49 50 dev_dbg(dssdev->dev, "enable\n"); 51 52 if (!omapdss_device_is_connected(dssdev)) 53 return -ENODEV; 54 55 if (omapdss_device_is_enabled(dssdev)) 56 return 0; 57 58 r = src->ops->enable(src); 59 if (r) 60 return r; 61 62 if (ddata->enable_gpio) 63 gpiod_set_value_cansleep(ddata->enable_gpio, 1); 64 65 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 66 67 return 0; 68} 69 70static void opa362_disable(struct omap_dss_device *dssdev) 71{ 72 struct panel_drv_data *ddata = to_panel_data(dssdev); 73 struct omap_dss_device *src = dssdev->src; 74 75 dev_dbg(dssdev->dev, "disable\n"); 76 77 if (!omapdss_device_is_enabled(dssdev)) 78 return; 79 80 if (ddata->enable_gpio) 81 gpiod_set_value_cansleep(ddata->enable_gpio, 0); 82 83 src->ops->disable(src); 84 85 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 86} 87 88static const struct omap_dss_device_ops opa362_ops = { 89 .connect = opa362_connect, 90 .disconnect = opa362_disconnect, 91 .enable = opa362_enable, 92 .disable = opa362_disable, 93}; 94 95static int opa362_probe(struct platform_device *pdev) 96{ 97 struct panel_drv_data *ddata; 98 struct omap_dss_device *dssdev; 99 struct gpio_desc *gpio; 100 101 dev_dbg(&pdev->dev, "probe\n"); 102 103 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); 104 if (!ddata) 105 return -ENOMEM; 106 107 platform_set_drvdata(pdev, ddata); 108 109 gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); 110 if (IS_ERR(gpio)) 111 return PTR_ERR(gpio); 112 113 ddata->enable_gpio = gpio; 114 115 dssdev = &ddata->dssdev; 116 dssdev->ops = &opa362_ops; 117 dssdev->dev = &pdev->dev; 118 dssdev->type = OMAP_DISPLAY_TYPE_VENC; 119 dssdev->output_type = OMAP_DISPLAY_TYPE_VENC; 120 dssdev->owner = THIS_MODULE; 121 dssdev->of_ports = BIT(1) | BIT(0); 122 123 dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1); 124 if (IS_ERR(dssdev->next)) { 125 if (PTR_ERR(dssdev->next) != -EPROBE_DEFER) 126 dev_err(&pdev->dev, "failed to find video sink\n"); 127 return PTR_ERR(dssdev->next); 128 } 129 130 omapdss_device_register(dssdev); 131 132 return 0; 133} 134 135static int __exit opa362_remove(struct platform_device *pdev) 136{ 137 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 138 struct omap_dss_device *dssdev = &ddata->dssdev; 139 140 if (dssdev->next) 141 omapdss_device_put(dssdev->next); 142 omapdss_device_unregister(&ddata->dssdev); 143 144 WARN_ON(omapdss_device_is_enabled(dssdev)); 145 if (omapdss_device_is_enabled(dssdev)) 146 opa362_disable(dssdev); 147 148 WARN_ON(omapdss_device_is_connected(dssdev)); 149 if (omapdss_device_is_connected(dssdev)) 150 omapdss_device_disconnect(NULL, dssdev); 151 152 return 0; 153} 154 155static const struct of_device_id opa362_of_match[] = { 156 { .compatible = "omapdss,ti,opa362", }, 157 {}, 158}; 159MODULE_DEVICE_TABLE(of, opa362_of_match); 160 161static struct platform_driver opa362_driver = { 162 .probe = opa362_probe, 163 .remove = __exit_p(opa362_remove), 164 .driver = { 165 .name = "amplifier-opa362", 166 .of_match_table = opa362_of_match, 167 .suppress_bind_attrs = true, 168 }, 169}; 170 171module_platform_driver(opa362_driver); 172 173MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>"); 174MODULE_DESCRIPTION("OPA362 analog video amplifier with output/power control"); 175MODULE_LICENSE("GPL v2");