diff --git a/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt index 54d7e31525ec..3f903af93949 100644 --- a/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt +++ b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt @@ -6,15 +6,25 @@ Required properties: Optional properties: - powerdown-gpios: power-down gpio -- reg: I2C address. If and only if present the device node - should be placed into the i2c controller node where the - tfp410 i2c is connected to. +- reg: I2C address. If and only if present the device node should be placed + into the I2C controller node where the TFP410 I2C is connected to. +- ti,deskew: data de-skew in 350ps increments, from -4 to +3, as configured + through th DK[3:1] pins. This property shall be present only if the TFP410 + is not connected through I2C. Required nodes: -- Video port 0 for DPI input [1]. -- Video port 1 for DVI output [1]. -[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +This device has two video ports. Their connections are modeled using the OF +graph bindings specified in [1]. Each port node shall have a single endpoint. + +- Port 0 is the DPI input port. Its endpoint subnode shall contain a + pclk-sample property and a remote-endpoint property as specified in [1]. + +- Port 1 is the DVI output port. Its endpoint subnode shall contain a + remote-endpoint property is specified in [1]. + +[1] Documentation/devicetree/bindings/media/video-interfaces.txt + Example ------- @@ -22,6 +32,7 @@ Example tfp410: encoder@0 { compatible = "ti,tfp410"; powerdown-gpios = <&twl_gpio 2 GPIO_ACTIVE_LOW>; + ti,deskew = <4>; ports { #address-cells = <1>; @@ -31,6 +42,7 @@ tfp410: encoder@0 { reg = <0>; tfp410_in: endpoint@0 { + pclk-sample = <1>; remote-endpoint = <&dpi_out>; }; }; diff --git a/Documentation/devicetree/bindings/display/panel/osddisplays,osd070t1718-19ts.txt b/Documentation/devicetree/bindings/display/panel/osddisplays,osd070t1718-19ts.txt new file mode 100644 index 000000000000..e57883ccdf2f --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/osddisplays,osd070t1718-19ts.txt @@ -0,0 +1,12 @@ +OSD Displays OSD070T1718-19TS 7" WVGA TFT LCD panel + +Required properties: +- compatible: shall be "osddisplays,osd070t1718-19ts" +- power-supply: see simple-panel.txt + +Optional properties: +- backlight: see simple-panel.txt + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. No other simple-panel properties than +the ones specified herein are valid. diff --git a/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt b/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt index ed34253d9fb1..898e06ecf4ef 100644 --- a/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt +++ b/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt @@ -6,6 +6,7 @@ Required properties: Optional properties: - label: a symbolic name for the panel +- backlight: phandle of the backlight device Required nodes: - Video port for DPI input @@ -21,6 +22,7 @@ lcd-panel: td028ttec1@0 { spi-cpha; label = "lcd"; + backlight = <&backlight>; port { lcd_in: endpoint { remote-endpoint = <&dpi_out>; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 8162b0eb4b50..7db1945a95f7 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -302,6 +302,7 @@ oranth Shenzhen Oranth Technology Co., Ltd. ORCL Oracle Corporation orisetech Orise Technology ortustech Ortus Technology Co., Ltd. +osddisplays OSD Displays ovti OmniVision Technologies oxsemi Oxford Semiconductor, Ltd. panasonic Panasonic Corporation diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index 0805801f4e94..e64736c39a9f 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -234,7 +234,7 @@ static int dumb_vga_remove(struct platform_device *pdev) */ static const struct drm_bridge_timings default_dac_timings = { /* Timing specifications, datasheet page 7 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE, .setup_time_ps = 500, .hold_time_ps = 1500, }; @@ -245,7 +245,7 @@ static const struct drm_bridge_timings default_dac_timings = { */ static const struct drm_bridge_timings ti_ths8134_dac_timings = { /* From timing diagram, datasheet page 9 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE, /* From datasheet, page 12 */ .setup_time_ps = 3000, /* I guess this means latched input */ @@ -258,7 +258,7 @@ static const struct drm_bridge_timings ti_ths8134_dac_timings = { */ static const struct drm_bridge_timings ti_ths8135_dac_timings = { /* From timing diagram, datasheet page 14 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE, /* From datasheet, page 16 */ .setup_time_ps = 2000, .hold_time_ps = 500, diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 888980d4bc74..e570c9dee180 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1222,8 +1222,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge) &bus_format, 1); tc->connector.display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH | - DRM_BUS_FLAG_PIXDATA_NEGEDGE | - DRM_BUS_FLAG_SYNC_NEGEDGE; + DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE | + DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE; drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder); return 0; diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index 7bfb4f338813..285be4a0f4bd 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -27,10 +27,14 @@ struct tfp410 { struct drm_bridge bridge; struct drm_connector connector; + unsigned int connector_type; struct i2c_adapter *ddc; struct gpio_desc *hpd; struct delayed_work hpd_work; + struct gpio_desc *powerdown; + + struct drm_bridge_timings timings; struct device *dev; }; @@ -126,7 +130,7 @@ static int tfp410_attach(struct drm_bridge *bridge) drm_connector_helper_add(&dvi->connector, &tfp410_con_helper_funcs); ret = drm_connector_init(bridge->dev, &dvi->connector, - &tfp410_con_funcs, DRM_MODE_CONNECTOR_HDMIA); + &tfp410_con_funcs, dvi->connector_type); if (ret) { dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret); return ret; @@ -138,8 +142,24 @@ static int tfp410_attach(struct drm_bridge *bridge) return 0; } +static void tfp410_enable(struct drm_bridge *bridge) +{ + struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); + + gpiod_set_value_cansleep(dvi->powerdown, 0); +} + +static void tfp410_disable(struct drm_bridge *bridge) +{ + struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); + + gpiod_set_value_cansleep(dvi->powerdown, 1); +} + static const struct drm_bridge_funcs tfp410_bridge_funcs = { .attach = tfp410_attach, + .enable = tfp410_enable, + .disable = tfp410_disable, }; static void tfp410_hpd_work_func(struct work_struct *work) @@ -162,6 +182,70 @@ static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg) return IRQ_HANDLED; } +static const struct drm_bridge_timings tfp410_default_timings = { + .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE + | DRM_BUS_FLAG_DE_HIGH, + .setup_time_ps = 1200, + .hold_time_ps = 1300, +}; + +static int tfp410_parse_timings(struct tfp410 *dvi, bool i2c) +{ + struct drm_bridge_timings *timings = &dvi->timings; + struct device_node *ep; + u32 pclk_sample = 0; + s32 deskew = 0; + + /* Start with defaults. */ + *timings = tfp410_default_timings; + + if (i2c) + /* + * In I2C mode timings are configured through the I2C interface. + * As the driver doesn't support I2C configuration yet, we just + * go with the defaults (BSEL=1, DSEL=1, DKEN=0, EDGE=1). + */ + return 0; + + /* + * In non-I2C mode, timings are configured through the BSEL, DSEL, DKEN + * and EDGE pins. They are specified in DT through endpoint properties + * and vendor-specific properties. + */ + ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 0, 0); + if (!ep) + return -EINVAL; + + /* Get the sampling edge from the endpoint. */ + of_property_read_u32(ep, "pclk-sample", &pclk_sample); + of_node_put(ep); + + timings->input_bus_flags = DRM_BUS_FLAG_DE_HIGH; + + switch (pclk_sample) { + case 0: + timings->input_bus_flags |= DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE + | DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE; + break; + case 1: + timings->input_bus_flags |= DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE + | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE; + break; + default: + return -EINVAL; + } + + /* Get the setup and hold time from vendor-specific properties. */ + of_property_read_u32(dvi->dev->of_node, "ti,deskew", (u32 *)&deskew); + if (deskew < -4 || deskew > 3) + return -EINVAL; + + timings->setup_time_ps = min(0, 1200 - 350 * deskew); + timings->hold_time_ps = min(0, 1300 + 350 * deskew); + + return 0; +} + static int tfp410_get_connector_properties(struct tfp410 *dvi) { struct device_node *connector_node, *ddc_phandle; @@ -172,6 +256,11 @@ static int tfp410_get_connector_properties(struct tfp410 *dvi) if (!connector_node) return -ENODEV; + if (of_device_is_compatible(connector_node, "hdmi-connector")) + dvi->connector_type = DRM_MODE_CONNECTOR_HDMIA; + else + dvi->connector_type = DRM_MODE_CONNECTOR_DVID; + dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode, "hpd-gpios", 0, GPIOD_IN, "hpd"); if (IS_ERR(dvi->hpd)) { @@ -200,7 +289,7 @@ static int tfp410_get_connector_properties(struct tfp410 *dvi) return ret; } -static int tfp410_init(struct device *dev) +static int tfp410_init(struct device *dev, bool i2c) { struct tfp410 *dvi; int ret; @@ -217,12 +306,24 @@ static int tfp410_init(struct device *dev) dvi->bridge.funcs = &tfp410_bridge_funcs; dvi->bridge.of_node = dev->of_node; + dvi->bridge.timings = &dvi->timings; dvi->dev = dev; + ret = tfp410_parse_timings(dvi, i2c); + if (ret) + goto fail; + ret = tfp410_get_connector_properties(dvi); if (ret) goto fail; + dvi->powerdown = devm_gpiod_get_optional(dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(dvi->powerdown)) { + dev_err(dev, "failed to parse powerdown gpio\n"); + return PTR_ERR(dvi->powerdown); + } + if (dvi->hpd) { INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func); @@ -264,7 +365,7 @@ static int tfp410_fini(struct device *dev) static int tfp410_probe(struct platform_device *pdev) { - return tfp410_init(&pdev->dev); + return tfp410_init(&pdev->dev, false); } static int tfp410_remove(struct platform_device *pdev) @@ -301,7 +402,7 @@ static int tfp410_i2c_probe(struct i2c_client *client, return -ENXIO; } - return tfp410_init(&client->dev); + return tfp410_init(&client->dev, true); } static int tfp410_i2c_remove(struct i2c_client *client) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 40ac19848034..3b7eb58817f0 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -495,7 +495,7 @@ mode_fixup(struct drm_atomic_state *state) static enum drm_mode_status mode_valid_path(struct drm_connector *connector, struct drm_encoder *encoder, struct drm_crtc *crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { enum drm_mode_status ret; @@ -534,7 +534,7 @@ mode_valid(struct drm_atomic_state *state) struct drm_crtc *crtc = conn_state->crtc; struct drm_crtc_state *crtc_state; enum drm_mode_status mode_status; - struct drm_display_mode *mode; + const struct drm_display_mode *mode; if (!crtc || !encoder) continue; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 869ac6f4671e..56f92a0bba62 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -655,22 +655,22 @@ EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); * @bus_flags: information about pixelclk, sync and DE polarity will be stored * here * - * Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE and - * DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS + * Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE + * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS * found in @vm */ void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags) { *bus_flags = 0; if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) - *bus_flags |= DRM_BUS_FLAG_PIXDATA_POSEDGE; + *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE; if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) - *bus_flags |= DRM_BUS_FLAG_PIXDATA_NEGEDGE; + *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE) - *bus_flags |= DRM_BUS_FLAG_SYNC_POSEDGE; + *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE; if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE) - *bus_flags |= DRM_BUS_FLAG_SYNC_NEGEDGE; + *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE; if (vm->flags & DISPLAY_FLAGS_DE_LOW) *bus_flags |= DRM_BUS_FLAG_DE_LOW; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index bf256971063d..83c841b50272 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -94,7 +94,7 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) drm_display_mode_to_videomode(mode, &vm); /* INV_PXCK as default (most display sample data on rising edge) */ - if (!(con->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)) + if (!(con->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)) pol |= DCU_SYN_POL_INV_PXCK; if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW) diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index ec3602ebbc1c..311a20c942eb 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -295,7 +295,7 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) sig_cfg.enable_pol = !(imx_crtc_state->bus_flags & DRM_BUS_FLAG_DE_LOW); /* Default to driving pixel data on negative clock edges */ sig_cfg.clk_pol = !!(imx_crtc_state->bus_flags & - DRM_BUS_FLAG_PIXDATA_POSEDGE); + DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE); sig_cfg.bus_format = imx_crtc_state->bus_format; sig_cfg.v_to_h_sync = 0; sig_cfg.hsync_pin = imx_crtc_state->di_hsync_pin; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 0ee1ca8a316a..98e9bda91e80 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -253,12 +253,12 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) if (!(bus_flags & DRM_BUS_FLAG_DE_LOW)) vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; /* - * DRM_BUS_FLAG_PIXDATA_ defines are controller centric, + * DRM_BUS_FLAG_PIXDATA_DRIVE_ defines are controller centric, * controllers VDCTRL0_DOTCLK is display centric. * Drive on positive edge -> display samples on falling edge - * DRM_BUS_FLAG_PIXDATA_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING + * DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING */ - if (bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE) + if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING; writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0); diff --git a/drivers/gpu/drm/omapdrm/displays/Kconfig b/drivers/gpu/drm/omapdrm/displays/Kconfig index a349cb61961e..7b0bcb494b5c 100644 --- a/drivers/gpu/drm/omapdrm/displays/Kconfig +++ b/drivers/gpu/drm/omapdrm/displays/Kconfig @@ -6,23 +6,12 @@ config DRM_OMAP_ENCODER_OPA362 Driver for OPA362 external analog TV amplifier controlled through a GPIO. -config DRM_OMAP_ENCODER_TFP410 - tristate "TFP410 DPI to DVI Encoder" - help - Driver for TFP410 DPI to DVI encoder. - config DRM_OMAP_ENCODER_TPD12S015 tristate "TPD12S015 HDMI ESD protection and level shifter" help Driver for TPD12S015, which offers HDMI ESD protection and level shifting. -config DRM_OMAP_CONNECTOR_DVI - tristate "DVI Connector" - depends on I2C - help - Driver for a generic DVI connector. - config DRM_OMAP_CONNECTOR_HDMI tristate "HDMI Connector" help @@ -33,12 +22,6 @@ config DRM_OMAP_CONNECTOR_ANALOG_TV help Driver for a generic analog TV connector. -config DRM_OMAP_PANEL_DPI - tristate "Generic DPI panel" - depends on BACKLIGHT_CLASS_DEVICE - help - Driver for generic DPI panels. - config DRM_OMAP_PANEL_DSI_CM tristate "Generic DSI Command Mode Panel" depends on BACKLIGHT_CLASS_DEVICE diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile b/drivers/gpu/drm/omapdrm/displays/Makefile index d99659e1381b..1db34d4fed64 100644 --- a/drivers/gpu/drm/omapdrm/displays/Makefile +++ b/drivers/gpu/drm/omapdrm/displays/Makefile @@ -1,11 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_OMAP_ENCODER_OPA362) += encoder-opa362.o -obj-$(CONFIG_DRM_OMAP_ENCODER_TFP410) += encoder-tfp410.o obj-$(CONFIG_DRM_OMAP_ENCODER_TPD12S015) += encoder-tpd12s015.o -obj-$(CONFIG_DRM_OMAP_CONNECTOR_DVI) += connector-dvi.o obj-$(CONFIG_DRM_OMAP_CONNECTOR_HDMI) += connector-hdmi.o obj-$(CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV) += connector-analog-tv.o -obj-$(CONFIG_DRM_OMAP_PANEL_DPI) += panel-dpi.o obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o obj-$(CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 28a3ce8f88d2..6c0561101874 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -35,50 +35,9 @@ static void tvc_disconnect(struct omap_dss_device *src, { } -static int tvc_enable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - int r; - - dev_dbg(ddata->dev, "enable\n"); - - if (!omapdss_device_is_connected(dssdev)) - return -ENODEV; - - if (omapdss_device_is_enabled(dssdev)) - return 0; - - r = src->ops->enable(src); - if (r) - return r; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return r; -} - -static void tvc_disable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - - dev_dbg(ddata->dev, "disable\n"); - - if (!omapdss_device_is_enabled(dssdev)) - return; - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -} - static const struct omap_dss_device_ops tvc_ops = { .connect = tvc_connect, .disconnect = tvc_disconnect, - - .enable = tvc_enable, - .disable = tvc_disable, }; static int tvc_probe(struct platform_device *pdev) @@ -97,6 +56,7 @@ static int tvc_probe(struct platform_device *pdev) dssdev->ops = &tvc_ops; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_VENC; + dssdev->display = true; dssdev->owner = THIS_MODULE; dssdev->of_ports = BIT(0); @@ -109,12 +69,9 @@ static int tvc_probe(struct platform_device *pdev) static int __exit tvc_remove(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *dssdev = &ddata->dssdev; omapdss_device_unregister(&ddata->dssdev); - tvc_disable(dssdev); - return 0; } diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c deleted file mode 100644 index 24b14f44248e..000000000000 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Generic DVI Connector driver - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * Author: Tomi Valkeinen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include - -#include "../dss/omapdss.h" - -struct panel_drv_data { - struct omap_dss_device dssdev; - - struct i2c_adapter *i2c_adapter; - - struct gpio_desc *hpd_gpio; - - void (*hpd_cb)(void *cb_data, enum drm_connector_status status); - void *hpd_cb_data; - bool hpd_enabled; - /* mutex for hpd fields above */ - struct mutex hpd_lock; -}; - -#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) - -static int dvic_connect(struct omap_dss_device *src, - struct omap_dss_device *dst) -{ - return 0; -} - -static void dvic_disconnect(struct omap_dss_device *src, - struct omap_dss_device *dst) -{ -} - -static int dvic_enable(struct omap_dss_device *dssdev) -{ - struct omap_dss_device *src = dssdev->src; - int r; - - if (!omapdss_device_is_connected(dssdev)) - return -ENODEV; - - if (omapdss_device_is_enabled(dssdev)) - return 0; - - r = src->ops->enable(src); - if (r) - return r; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return 0; -} - -static void dvic_disable(struct omap_dss_device *dssdev) -{ - struct omap_dss_device *src = dssdev->src; - - if (!omapdss_device_is_enabled(dssdev)) - return; - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -} - -static int dvic_ddc_read(struct i2c_adapter *adapter, - unsigned char *buf, u16 count, u8 offset) -{ - int r, retries; - - for (retries = 3; retries > 0; retries--) { - struct i2c_msg msgs[] = { - { - .addr = DDC_ADDR, - .flags = 0, - .len = 1, - .buf = &offset, - }, { - .addr = DDC_ADDR, - .flags = I2C_M_RD, - .len = count, - .buf = buf, - } - }; - - r = i2c_transfer(adapter, msgs, 2); - if (r == 2) - return 0; - - if (r != -EAGAIN) - break; - } - - return r < 0 ? r : -EIO; -} - -static int dvic_read_edid(struct omap_dss_device *dssdev, - u8 *edid, int len) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - int r, l, bytes_read; - - l = min(EDID_LENGTH, len); - r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0); - if (r) - return r; - - bytes_read = l; - - /* if there are extensions, read second block */ - if (len > EDID_LENGTH && edid[0x7e] > 0) { - l = min(EDID_LENGTH, len - EDID_LENGTH); - - r = dvic_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH, - l, EDID_LENGTH); - if (r) - return r; - - bytes_read += l; - } - - return bytes_read; -} - -static bool dvic_detect(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - unsigned char out; - int r; - - if (ddata->hpd_gpio) - return gpiod_get_value_cansleep(ddata->hpd_gpio); - - if (!ddata->i2c_adapter) - return true; - - r = dvic_ddc_read(ddata->i2c_adapter, &out, 1, 0); - - return r == 0; -} - -static void dvic_register_hpd_cb(struct omap_dss_device *dssdev, - void (*cb)(void *cb_data, - enum drm_connector_status status), - void *cb_data) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - mutex_lock(&ddata->hpd_lock); - ddata->hpd_cb = cb; - ddata->hpd_cb_data = cb_data; - mutex_unlock(&ddata->hpd_lock); -} - -static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - mutex_lock(&ddata->hpd_lock); - ddata->hpd_cb = NULL; - ddata->hpd_cb_data = NULL; - mutex_unlock(&ddata->hpd_lock); -} - -static const struct omap_dss_device_ops dvic_ops = { - .connect = dvic_connect, - .disconnect = dvic_disconnect, - - .enable = dvic_enable, - .disable = dvic_disable, - - .read_edid = dvic_read_edid, - .detect = dvic_detect, - - .register_hpd_cb = dvic_register_hpd_cb, - .unregister_hpd_cb = dvic_unregister_hpd_cb, -}; - -static irqreturn_t dvic_hpd_isr(int irq, void *data) -{ - struct panel_drv_data *ddata = data; - - mutex_lock(&ddata->hpd_lock); - if (ddata->hpd_enabled && ddata->hpd_cb) { - enum drm_connector_status status; - - if (dvic_detect(&ddata->dssdev)) - status = connector_status_connected; - else - status = connector_status_disconnected; - - ddata->hpd_cb(ddata->hpd_cb_data, status); - } - mutex_unlock(&ddata->hpd_lock); - - return IRQ_HANDLED; -} - -static int dvic_probe_of(struct platform_device *pdev) -{ - struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct device_node *node = pdev->dev.of_node; - struct device_node *adapter_node; - struct i2c_adapter *adapter; - struct gpio_desc *gpio; - int r; - - gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); - if (IS_ERR(gpio)) { - dev_err(&pdev->dev, "failed to parse HPD gpio\n"); - return PTR_ERR(gpio); - } - - ddata->hpd_gpio = gpio; - - mutex_init(&ddata->hpd_lock); - - if (ddata->hpd_gpio) { - r = devm_request_threaded_irq(&pdev->dev, - gpiod_to_irq(ddata->hpd_gpio), NULL, dvic_hpd_isr, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "DVI HPD", ddata); - if (r) - return r; - } - - adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); - if (adapter_node) { - adapter = of_get_i2c_adapter_by_node(adapter_node); - of_node_put(adapter_node); - if (adapter == NULL) { - dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n"); - return -EPROBE_DEFER; - } - - ddata->i2c_adapter = adapter; - } - - return 0; -} - -static int dvic_probe(struct platform_device *pdev) -{ - struct panel_drv_data *ddata; - struct omap_dss_device *dssdev; - int r; - - ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); - if (!ddata) - return -ENOMEM; - - platform_set_drvdata(pdev, ddata); - - r = dvic_probe_of(pdev); - if (r) - return r; - - dssdev = &ddata->dssdev; - dssdev->ops = &dvic_ops; - dssdev->dev = &pdev->dev; - dssdev->type = OMAP_DISPLAY_TYPE_DVI; - dssdev->owner = THIS_MODULE; - dssdev->of_ports = BIT(0); - - if (ddata->hpd_gpio) - dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT - | OMAP_DSS_DEVICE_OP_HPD; - if (ddata->i2c_adapter) - dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT - | OMAP_DSS_DEVICE_OP_EDID; - - omapdss_display_init(dssdev); - omapdss_device_register(dssdev); - - return 0; -} - -static int __exit dvic_remove(struct platform_device *pdev) -{ - struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *dssdev = &ddata->dssdev; - - omapdss_device_unregister(&ddata->dssdev); - - dvic_disable(dssdev); - - i2c_put_adapter(ddata->i2c_adapter); - - mutex_destroy(&ddata->hpd_lock); - - return 0; -} - -static const struct of_device_id dvic_of_match[] = { - { .compatible = "omapdss,dvi-connector", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, dvic_of_match); - -static struct platform_driver dvi_connector_driver = { - .probe = dvic_probe, - .remove = __exit_p(dvic_remove), - .driver = { - .name = "connector-dvi", - .of_match_table = dvic_of_match, - .suppress_bind_attrs = true, - }, -}; - -module_platform_driver(dvi_connector_driver); - -MODULE_AUTHOR("Tomi Valkeinen "); -MODULE_DESCRIPTION("Generic DVI Connector driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index e602fa4a50a4..68d6f6e44b03 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -41,44 +41,6 @@ static void hdmic_disconnect(struct omap_dss_device *src, { } -static int hdmic_enable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - int r; - - dev_dbg(ddata->dev, "enable\n"); - - if (!omapdss_device_is_connected(dssdev)) - return -ENODEV; - - if (omapdss_device_is_enabled(dssdev)) - return 0; - - r = src->ops->enable(src); - if (r) - return r; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return r; -} - -static void hdmic_disable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - - dev_dbg(ddata->dev, "disable\n"); - - if (!omapdss_device_is_enabled(dssdev)) - return; - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -} - static bool hdmic_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -113,9 +75,6 @@ static const struct omap_dss_device_ops hdmic_ops = { .connect = hdmic_connect, .disconnect = hdmic_disconnect, - .enable = hdmic_enable, - .disable = hdmic_disable, - .detect = hdmic_detect, .register_hpd_cb = hdmic_register_hpd_cb, .unregister_hpd_cb = hdmic_unregister_hpd_cb, @@ -181,6 +140,7 @@ static int hdmic_probe(struct platform_device *pdev) dssdev->ops = &hdmic_ops; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_HDMI; + dssdev->display = true; dssdev->owner = THIS_MODULE; dssdev->of_ports = BIT(0); dssdev->ops_flags = ddata->hpd_gpio @@ -196,12 +156,9 @@ static int hdmic_probe(struct platform_device *pdev) static int __exit hdmic_remove(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *dssdev = &ddata->dssdev; omapdss_device_unregister(&ddata->dssdev); - hdmic_disable(dssdev); - return 0; } diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c index 4fefd80f53bb..29a5a130ebd1 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c @@ -41,48 +41,20 @@ static void opa362_disconnect(struct omap_dss_device *src, omapdss_device_disconnect(dst, dst->next); } -static int opa362_enable(struct omap_dss_device *dssdev) +static void opa362_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - int r; - - dev_dbg(dssdev->dev, "enable\n"); - - if (!omapdss_device_is_connected(dssdev)) - return -ENODEV; - - if (omapdss_device_is_enabled(dssdev)) - return 0; - - r = src->ops->enable(src); - if (r) - return r; if (ddata->enable_gpio) gpiod_set_value_cansleep(ddata->enable_gpio, 1); - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return 0; } static void opa362_disable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - - dev_dbg(dssdev->dev, "disable\n"); - - if (!omapdss_device_is_enabled(dssdev)) - return; if (ddata->enable_gpio) gpiod_set_value_cansleep(ddata->enable_gpio, 0); - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } static const struct omap_dss_device_ops opa362_ops = { @@ -116,7 +88,6 @@ static int opa362_probe(struct platform_device *pdev) dssdev->ops = &opa362_ops; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_VENC; - dssdev->output_type = OMAP_DISPLAY_TYPE_VENC; dssdev->owner = THIS_MODULE; dssdev->of_ports = BIT(1) | BIT(0); @@ -141,13 +112,7 @@ static int __exit opa362_remove(struct platform_device *pdev) omapdss_device_put(dssdev->next); omapdss_device_unregister(&ddata->dssdev); - WARN_ON(omapdss_device_is_enabled(dssdev)); - if (omapdss_device_is_enabled(dssdev)) - opa362_disable(dssdev); - - WARN_ON(omapdss_device_is_connected(dssdev)); - if (omapdss_device_is_connected(dssdev)) - omapdss_device_disconnect(NULL, dssdev); + opa362_disable(dssdev); return 0; } diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c deleted file mode 100644 index f1a748353279..000000000000 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * TFP410 DPI-to-DVI encoder driver - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * Author: Tomi Valkeinen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "../dss/omapdss.h" - -struct panel_drv_data { - struct omap_dss_device dssdev; - - struct gpio_desc *pd_gpio; -}; - -#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) - -static int tfp410_connect(struct omap_dss_device *src, - struct omap_dss_device *dst) -{ - return omapdss_device_connect(dst->dss, dst, dst->next); -} - -static void tfp410_disconnect(struct omap_dss_device *src, - struct omap_dss_device *dst) -{ - omapdss_device_disconnect(dst, dst->next); -} - -static int tfp410_enable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - int r; - - if (!omapdss_device_is_connected(dssdev)) - return -ENODEV; - - if (omapdss_device_is_enabled(dssdev)) - return 0; - - r = src->ops->enable(src); - if (r) - return r; - - if (ddata->pd_gpio) - gpiod_set_value_cansleep(ddata->pd_gpio, 0); - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return 0; -} - -static void tfp410_disable(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; - - if (!omapdss_device_is_enabled(dssdev)) - return; - - if (ddata->pd_gpio) - gpiod_set_value_cansleep(ddata->pd_gpio, 0); - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -} - -static const struct omap_dss_device_ops tfp410_ops = { - .connect = tfp410_connect, - .disconnect = tfp410_disconnect, - .enable = tfp410_enable, - .disable = tfp410_disable, -}; - -static int tfp410_probe(struct platform_device *pdev) -{ - struct panel_drv_data *ddata; - struct omap_dss_device *dssdev; - struct gpio_desc *gpio; - - ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); - if (!ddata) - return -ENOMEM; - - platform_set_drvdata(pdev, ddata); - - /* Powerdown GPIO */ - gpio = devm_gpiod_get_optional(&pdev->dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(gpio)) { - dev_err(&pdev->dev, "failed to parse powerdown gpio\n"); - return PTR_ERR(gpio); - } - - ddata->pd_gpio = gpio; - - dssdev = &ddata->dssdev; - dssdev->ops = &tfp410_ops; - dssdev->dev = &pdev->dev; - dssdev->type = OMAP_DISPLAY_TYPE_DPI; - dssdev->output_type = OMAP_DISPLAY_TYPE_DVI; - dssdev->owner = THIS_MODULE; - dssdev->of_ports = BIT(1) | BIT(0); - dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_POSEDGE - | DRM_BUS_FLAG_PIXDATA_POSEDGE; - - dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1); - if (IS_ERR(dssdev->next)) { - if (PTR_ERR(dssdev->next) != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to find video sink\n"); - return PTR_ERR(dssdev->next); - } - - omapdss_device_register(dssdev); - - return 0; -} - -static int __exit tfp410_remove(struct platform_device *pdev) -{ - struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *dssdev = &ddata->dssdev; - - if (dssdev->next) - omapdss_device_put(dssdev->next); - omapdss_device_unregister(&ddata->dssdev); - - WARN_ON(omapdss_device_is_enabled(dssdev)); - if (omapdss_device_is_enabled(dssdev)) - tfp410_disable(dssdev); - - WARN_ON(omapdss_device_is_connected(dssdev)); - if (omapdss_device_is_connected(dssdev)) - omapdss_device_disconnect(NULL, dssdev); - - return 0; -} - -static const struct of_device_id tfp410_of_match[] = { - { .compatible = "omapdss,ti,tfp410", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, tfp410_of_match); - -static struct platform_driver tfp410_driver = { - .probe = tfp410_probe, - .remove = __exit_p(tfp410_remove), - .driver = { - .name = "tfp410", - .of_match_table = tfp410_of_match, - .suppress_bind_attrs = true, - }, -}; - -module_platform_driver(tfp410_driver); - -MODULE_AUTHOR("Tomi Valkeinen "); -MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index 94de55fd8884..bc03752d2762 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -62,35 +62,6 @@ static void tpd_disconnect(struct omap_dss_device *src, omapdss_device_disconnect(dst, dst->next); } -static int tpd_enable(struct omap_dss_device *dssdev) -{ - struct omap_dss_device *src = dssdev->src; - int r; - - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) - return 0; - - r = src->ops->enable(src); - if (r) - return r; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return r; -} - -static void tpd_disable(struct omap_dss_device *dssdev) -{ - struct omap_dss_device *src = dssdev->src; - - if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) - return; - - src->ops->disable(src); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -} - static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -124,8 +95,6 @@ static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev) static const struct omap_dss_device_ops tpd_ops = { .connect = tpd_connect, .disconnect = tpd_disconnect, - .enable = tpd_enable, - .disable = tpd_disable, .detect = tpd_detect, .register_hpd_cb = tpd_register_hpd_cb, .unregister_hpd_cb = tpd_unregister_hpd_cb, @@ -198,7 +167,6 @@ static int tpd_probe(struct platform_device *pdev) dssdev->ops = &tpd_ops; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_HDMI; - dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; dssdev->owner = THIS_MODULE; dssdev->of_ports = BIT(1) | BIT(0); dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT @@ -225,14 +193,6 @@ static int __exit tpd_remove(struct platform_device *pdev) omapdss_device_put(dssdev->next); omapdss_device_unregister(&ddata->dssdev); - WARN_ON(omapdss_device_is_enabled(dssdev)); - if (omapdss_device_is_enabled(dssdev)) - tpd_disable(dssdev); - - WARN_ON(omapdss_device_is_connected(dssdev)); - if (omapdss_device_is_connected(dssdev)) - omapdss_device_disconnect(NULL, dssdev); - return 0; } diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c deleted file mode 100644 index 465120809eb3..000000000000 --- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Generic MIPI DPI Panel Driver - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * Author: Tomi Valkeinen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include