Lines Matching +full:mixer +full:- +full:tcon
1 // SPDX-License-Identifier: GPL-2.0+
14 #include <dt-bindings/clock/sun8i-tcon-top.h>
28 int sun8i_tcon_top_set_hdmi_src(struct device *dev, int tcon) in sun8i_tcon_top_set_hdmi_src() argument
34 if (!sun8i_tcon_top_node_is_tcon_top(dev->of_node)) { in sun8i_tcon_top_set_hdmi_src()
35 dev_err(dev, "Device is not TCON TOP!\n"); in sun8i_tcon_top_set_hdmi_src()
36 return -EINVAL; in sun8i_tcon_top_set_hdmi_src()
39 if (tcon < 2 || tcon > 3) { in sun8i_tcon_top_set_hdmi_src()
40 dev_err(dev, "TCON index must be 2 or 3!\n"); in sun8i_tcon_top_set_hdmi_src()
41 return -EINVAL; in sun8i_tcon_top_set_hdmi_src()
44 spin_lock_irqsave(&tcon_top->reg_lock, flags); in sun8i_tcon_top_set_hdmi_src()
46 val = readl(tcon_top->regs + TCON_TOP_GATE_SRC_REG); in sun8i_tcon_top_set_hdmi_src()
48 val |= FIELD_PREP(TCON_TOP_HDMI_SRC_MSK, tcon - 1); in sun8i_tcon_top_set_hdmi_src()
49 writel(val, tcon_top->regs + TCON_TOP_GATE_SRC_REG); in sun8i_tcon_top_set_hdmi_src()
51 spin_unlock_irqrestore(&tcon_top->reg_lock, flags); in sun8i_tcon_top_set_hdmi_src()
57 int sun8i_tcon_top_de_config(struct device *dev, int mixer, int tcon) in sun8i_tcon_top_de_config() argument
63 if (!sun8i_tcon_top_node_is_tcon_top(dev->of_node)) { in sun8i_tcon_top_de_config()
64 dev_err(dev, "Device is not TCON TOP!\n"); in sun8i_tcon_top_de_config()
65 return -EINVAL; in sun8i_tcon_top_de_config()
68 if (mixer > 1) { in sun8i_tcon_top_de_config()
69 dev_err(dev, "Mixer index is too high!\n"); in sun8i_tcon_top_de_config()
70 return -EINVAL; in sun8i_tcon_top_de_config()
73 if (tcon > 3) { in sun8i_tcon_top_de_config()
74 dev_err(dev, "TCON index is too high!\n"); in sun8i_tcon_top_de_config()
75 return -EINVAL; in sun8i_tcon_top_de_config()
78 spin_lock_irqsave(&tcon_top->reg_lock, flags); in sun8i_tcon_top_de_config()
80 reg = readl(tcon_top->regs + TCON_TOP_PORT_SEL_REG); in sun8i_tcon_top_de_config()
81 if (mixer == 0) { in sun8i_tcon_top_de_config()
83 reg |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, tcon); in sun8i_tcon_top_de_config()
86 reg |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, tcon); in sun8i_tcon_top_de_config()
88 writel(reg, tcon_top->regs + TCON_TOP_PORT_SEL_REG); in sun8i_tcon_top_de_config()
90 spin_unlock_irqrestore(&tcon_top->reg_lock, flags); in sun8i_tcon_top_de_config()
106 index = of_property_match_string(dev->of_node, "clock-names", parent); in sun8i_tcon_top_register_gate()
110 parent_name = of_clk_get_parent_name(dev->of_node, index); in sun8i_tcon_top_register_gate()
112 ret = of_property_read_string_index(dev->of_node, in sun8i_tcon_top_register_gate()
113 "clock-output-names", name_index, in sun8i_tcon_top_register_gate()
134 quirks = of_device_get_match_data(&pdev->dev); in sun8i_tcon_top_bind()
138 return -ENOMEM; in sun8i_tcon_top_bind()
143 return -ENOMEM; in sun8i_tcon_top_bind()
144 clk_data->num = CLK_NUM; in sun8i_tcon_top_bind()
145 tcon_top->clk_data = clk_data; in sun8i_tcon_top_bind()
147 spin_lock_init(&tcon_top->reg_lock); in sun8i_tcon_top_bind()
149 tcon_top->rst = devm_reset_control_get(dev, NULL); in sun8i_tcon_top_bind()
150 if (IS_ERR(tcon_top->rst)) { in sun8i_tcon_top_bind()
152 return PTR_ERR(tcon_top->rst); in sun8i_tcon_top_bind()
155 tcon_top->bus = devm_clk_get(dev, "bus"); in sun8i_tcon_top_bind()
156 if (IS_ERR(tcon_top->bus)) { in sun8i_tcon_top_bind()
158 return PTR_ERR(tcon_top->bus); in sun8i_tcon_top_bind()
162 tcon_top->regs = regs; in sun8i_tcon_top_bind()
166 ret = reset_control_deassert(tcon_top->rst); in sun8i_tcon_top_bind()
172 ret = clk_prepare_enable(tcon_top->bus); in sun8i_tcon_top_bind()
186 * TCON TOP has two muxes, which select parent clock for each TCON TV in sun8i_tcon_top_bind()
187 * channel clock. Parent could be either TCON TV or TVE clock. For now in sun8i_tcon_top_bind()
188 * we leave this fixed to TCON TV, since TVE driver for R40 is not yet in sun8i_tcon_top_bind()
190 * if TVE is active on each TCON TV. If it is, mux should be switched in sun8i_tcon_top_bind()
194 clk_data->hws[CLK_TCON_TOP_TV0] = in sun8i_tcon_top_bind()
195 sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs, in sun8i_tcon_top_bind()
196 &tcon_top->reg_lock, in sun8i_tcon_top_bind()
199 if (quirks->has_tcon_tv1) in sun8i_tcon_top_bind()
200 clk_data->hws[CLK_TCON_TOP_TV1] = in sun8i_tcon_top_bind()
201 sun8i_tcon_top_register_gate(dev, "tcon-tv1", regs, in sun8i_tcon_top_bind()
202 &tcon_top->reg_lock, in sun8i_tcon_top_bind()
205 if (quirks->has_dsi) in sun8i_tcon_top_bind()
206 clk_data->hws[CLK_TCON_TOP_DSI] = in sun8i_tcon_top_bind()
208 &tcon_top->reg_lock, in sun8i_tcon_top_bind()
212 if (IS_ERR(clk_data->hws[i])) { in sun8i_tcon_top_bind()
213 ret = PTR_ERR(clk_data->hws[i]); in sun8i_tcon_top_bind()
217 ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, in sun8i_tcon_top_bind()
228 if (!IS_ERR_OR_NULL(clk_data->hws[i])) in sun8i_tcon_top_bind()
229 clk_hw_unregister_gate(clk_data->hws[i]); in sun8i_tcon_top_bind()
230 clk_disable_unprepare(tcon_top->bus); in sun8i_tcon_top_bind()
232 reset_control_assert(tcon_top->rst); in sun8i_tcon_top_bind()
241 struct clk_hw_onecell_data *clk_data = tcon_top->clk_data; in sun8i_tcon_top_unbind()
244 of_clk_del_provider(dev->of_node); in sun8i_tcon_top_unbind()
246 if (clk_data->hws[i]) in sun8i_tcon_top_unbind()
247 clk_hw_unregister_gate(clk_data->hws[i]); in sun8i_tcon_top_unbind()
249 clk_disable_unprepare(tcon_top->bus); in sun8i_tcon_top_unbind()
250 reset_control_assert(tcon_top->rst); in sun8i_tcon_top_unbind()
260 return component_add(&pdev->dev, &sun8i_tcon_top_ops); in sun8i_tcon_top_probe()
265 component_del(&pdev->dev, &sun8i_tcon_top_ops); in sun8i_tcon_top_remove()
281 /* sun4i_drv uses this list to check if a device node is a TCON TOP */
284 .compatible = "allwinner,sun8i-r40-tcon-top",
288 .compatible = "allwinner,sun20i-d1-tcon-top",
292 .compatible = "allwinner,sun50i-h6-tcon-top",
304 .name = "sun8i-tcon-top",
311 MODULE_DESCRIPTION("Allwinner R40 TCON TOP driver");