// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> * Parts of this file were based on sources as follows: * * Copyright (C) 2006-2008 Intel Corporation * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com> * Copyright (C) 2007 Dave Airlie <airlied@linux.ie> * Copyright (C) 2011 Texas Instruments * Copyright (C) 2017 Eric Anholt
*/
/** * DOC: Faraday TV Encoder TVE200 DRM Driver * * The Faraday TV Encoder TVE200 is also known as the Gemini TV Interface * Controller (TVC) and is found in the Gemini Chipset from Storlink * Semiconductor (later Storm Semiconductor, later Cortina Systems) * but also in the Grain Media GM8180 chipset. On the Gemini the module * is connected to 8 data lines and a single clock line, comprising an * 8-bit BT.656 interface. * * This is a very basic YUV display driver. The datasheet specifies that * it supports the ITU BT.656 standard. It requires a 27 MHz clock which is * the hallmark of any TV encoder supporting both PAL and NTSC. * * This driver exposes a standard KMS interface for this TV encoder.
*/
ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
0, 0, &panel, &bridge); if (ret && ret != -ENODEV) return ret; if (panel) {
bridge = drm_panel_bridge_add_typed(panel,
DRM_MODE_CONNECTOR_Unknown); if (IS_ERR(bridge)) {
ret = PTR_ERR(bridge); goto out_bridge;
}
} else { /* * TODO: when we are using a different bridge than a panel * (such as a dumb VGA connector) we need to devise a different * method to get the connector out of the bridge.
*/
dev_err(dev->dev, "the bridge is not a panel\n");
ret = -EINVAL; goto out_bridge;
}
ret = tve200_display_init(dev); if (ret) {
dev_err(dev->dev, "failed to init display\n"); goto out_bridge;
}
ret = drm_simple_display_pipe_attach_bridge(&priv->pipe,
bridge); if (ret) {
dev_err(dev->dev, "failed to attach bridge\n"); goto out_bridge;
}
/* Clock the silicon so we can access the registers */
priv->pclk = devm_clk_get(dev, "PCLK"); if (IS_ERR(priv->pclk)) {
dev_err(dev, "unable to get PCLK\n");
ret = PTR_ERR(priv->pclk); goto dev_unref;
}
ret = clk_prepare_enable(priv->pclk); if (ret) {
dev_err(dev, "failed to enable PCLK\n"); goto dev_unref;
}
/* This clock is for the pixels (27MHz) */
priv->clk = devm_clk_get(dev, "TVE"); if (IS_ERR(priv->clk)) {
dev_err(dev, "unable to get TVE clock\n");
ret = PTR_ERR(priv->clk); goto clk_disable;
}
priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) {
dev_err(dev, "%s failed mmio\n", __func__);
ret = -EINVAL; goto clk_disable;
}
irq = platform_get_irq(pdev, 0); if (irq < 0) {
ret = irq; goto clk_disable;
}
/* turn off interrupts before requesting the irq */
writel(0, priv->regs + TVE200_INT_EN);
ret = devm_request_irq(dev, irq, tve200_irq, 0, "tve200", priv); if (ret) {
dev_err(dev, "failed to request irq %d\n", ret); goto clk_disable;
}
ret = tve200_modeset_init(drm); if (ret) goto clk_disable;
ret = drm_dev_register(drm, 0); if (ret < 0) goto clk_disable;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.