135 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/4 * Author: Archit Taneja <archit@ti.com>5 */6 7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/slab.h>11#include <linux/of.h>12#include <linux/of_graph.h>13 14#include <drm/drm_bridge.h>15#include <drm/drm_panel.h>16 17#include "dss.h"18#include "omapdss.h"19 20int omapdss_device_init_output(struct omap_dss_device *out,21 struct drm_bridge *local_bridge)22{23 struct device_node *remote_node;24 int ret;25 26 remote_node = of_graph_get_remote_node(out->dev->of_node,27 out->of_port, 0);28 if (!remote_node) {29 dev_dbg(out->dev, "failed to find video sink\n");30 return 0;31 }32 33 out->bridge = of_drm_find_bridge(remote_node);34 out->panel = of_drm_find_panel(remote_node);35 if (IS_ERR(out->panel))36 out->panel = NULL;37 38 of_node_put(remote_node);39 40 if (out->panel) {41 struct drm_bridge *bridge;42 43 bridge = drm_panel_bridge_add(out->panel);44 if (IS_ERR(bridge)) {45 dev_err(out->dev,46 "unable to create panel bridge (%ld)\n",47 PTR_ERR(bridge));48 ret = PTR_ERR(bridge);49 goto error;50 }51 52 out->bridge = bridge;53 }54 55 if (local_bridge) {56 if (!out->bridge) {57 ret = -EPROBE_DEFER;58 goto error;59 }60 61 out->next_bridge = out->bridge;62 out->bridge = local_bridge;63 }64 65 if (!out->bridge) {66 ret = -EPROBE_DEFER;67 goto error;68 }69 70 return 0;71 72error:73 omapdss_device_cleanup_output(out);74 return ret;75}76 77void omapdss_device_cleanup_output(struct omap_dss_device *out)78{79 if (out->bridge && out->panel)80 drm_panel_bridge_remove(out->next_bridge ?81 out->next_bridge : out->bridge);82}83 84void dss_mgr_set_timings(struct omap_dss_device *dssdev,85 const struct videomode *vm)86{87 omap_crtc_dss_set_timings(dssdev->dss->mgr_ops_priv,88 dssdev->dispc_channel, vm);89}90 91void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,92 const struct dss_lcd_mgr_config *config)93{94 omap_crtc_dss_set_lcd_config(dssdev->dss->mgr_ops_priv,95 dssdev->dispc_channel, config);96}97 98int dss_mgr_enable(struct omap_dss_device *dssdev)99{100 return omap_crtc_dss_enable(dssdev->dss->mgr_ops_priv,101 dssdev->dispc_channel);102}103 104void dss_mgr_disable(struct omap_dss_device *dssdev)105{106 omap_crtc_dss_disable(dssdev->dss->mgr_ops_priv,107 dssdev->dispc_channel);108}109 110void dss_mgr_start_update(struct omap_dss_device *dssdev)111{112 omap_crtc_dss_start_update(dssdev->dss->mgr_ops_priv,113 dssdev->dispc_channel);114}115 116int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,117 void (*handler)(void *), void *data)118{119 struct dss_device *dss = dssdev->dss;120 121 return omap_crtc_dss_register_framedone(dss->mgr_ops_priv,122 dssdev->dispc_channel,123 handler, data);124}125 126void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,127 void (*handler)(void *), void *data)128{129 struct dss_device *dss = dssdev->dss;130 131 omap_crtc_dss_unregister_framedone(dss->mgr_ops_priv,132 dssdev->dispc_channel,133 handler, data);134}135