1 /*
2 * Allwinner SoCs vdpo lowlevel driver.
3 *
4 * Copyright (C) 2017 Allwinner.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10 #include "drv_vdpo_lowlevel.h"
11
12 volatile struct __vdpo_dev *vdpo_dev[VDPO_NUM];
13
__vdpo_module_en(u32 dev_sel,u32 module_en,u32 sepa_sync_en)14 void __vdpo_module_en(u32 dev_sel, u32 module_en, u32 sepa_sync_en)
15 {
16 vdpo_dev[dev_sel]->module_ctrl.bits.separate_sync_en = sepa_sync_en;
17 vdpo_dev[dev_sel]->module_ctrl.bits.vdpo_mudule_en = module_en;
18 }
19
__vdpo_fmt_set(u32 dev_sel,u32 data_seq_sel,u32 sync_fmt,u32 data_width,u32 interlace)20 void __vdpo_fmt_set(u32 dev_sel, u32 data_seq_sel, u32 sync_fmt, u32 data_width,
21 u32 interlace)
22 {
23 vdpo_dev[dev_sel]->fmt_ctrl.bits.data_seq_sel = data_seq_sel;
24 vdpo_dev[dev_sel]->fmt_ctrl.bits.embedded_sync_fmt = sync_fmt;
25 vdpo_dev[dev_sel]->fmt_ctrl.bits.output_data_width = data_width;
26 vdpo_dev[dev_sel]->fmt_ctrl.bits.interlace_mode = interlace;
27 }
28
__vdpo_chroma_spl_set(u32 dev_sel,u8 cr_type,u8 cb_type)29 void __vdpo_chroma_spl_set(u32 dev_sel, u8 cr_type, u8 cb_type)
30 {
31 vdpo_dev[dev_sel]->hor_spl_ctrl.bits.cb_hori_spl_type = cb_type;
32 vdpo_dev[dev_sel]->hor_spl_ctrl.bits.cr_hori_spl_type = cr_type;
33 }
34
__vdpo_clamp_set(u32 dev_sel,u16 y_min,u16 y_max,u16 cb_min,u16 cb_max,u16 cr_min,u16 cr_max)35 void __vdpo_clamp_set(u32 dev_sel, u16 y_min, u16 y_max, u16 cb_min, u16 cb_max,
36 u16 cr_min, u16 cr_max)
37 {
38 vdpo_dev[dev_sel]->clamp0.bits.y_val_range_min = y_min;
39 vdpo_dev[dev_sel]->clamp0.bits.y_val_range_max = y_max;
40 vdpo_dev[dev_sel]->clamp1.bits.cb_val_range_min = cb_min;
41 vdpo_dev[dev_sel]->clamp1.bits.cb_val_range_max = cb_max;
42 vdpo_dev[dev_sel]->clamp2.bits.cr_val_range_min = cr_min;
43 vdpo_dev[dev_sel]->clamp2.bits.cr_val_range_max = cr_max;
44 }
45
__vdpo_sync_pol_set(u32 dev_sel,u8 hb_pol,u8 vb_pol,u8 field_pol)46 void __vdpo_sync_pol_set(u32 dev_sel, u8 hb_pol, u8 vb_pol, u8 field_pol)
47 {
48 vdpo_dev[dev_sel]->sync_ctrl.bits.h_blank_pol = hb_pol;
49 vdpo_dev[dev_sel]->sync_ctrl.bits.v_blank_pol = vb_pol;
50 vdpo_dev[dev_sel]->sync_ctrl.bits.field_pol = field_pol;
51 }
52
__vdpo_dclk_adjust(u32 dev_sel,u8 dclk_invt,u8 dly_en,u8 dly_num)53 void __vdpo_dclk_adjust(u32 dev_sel, u8 dclk_invt, u8 dly_en, u8 dly_num)
54 {
55 vdpo_dev[dev_sel]->sync_ctrl.bits.dclk_invert = dclk_invt;
56 vdpo_dev[dev_sel]->sync_ctrl.bits.dclk_dly_num = dly_num;
57 vdpo_dev[dev_sel]->sync_ctrl.bits.dclk_dly_en = dly_en;
58 }
59
__vdpo_get_curline(u32 sel)60 u32 __vdpo_get_curline(u32 sel)
61 {
62 u32 line = vdpo_dev[sel]->status.bits.current_line;
63
64 return line;
65 }
66
__vdpo_get_field(u32 sel)67 u32 __vdpo_get_field(u32 sel)
68 {
69 u32 field = vdpo_dev[sel]->status.bits.field_pol_sta;
70
71 return field;
72 }
73
__vdpo_irq_en(u32 sel,u32 int_type,u32 line)74 s32 __vdpo_irq_en(u32 sel, u32 int_type, u32 line)
75 {
76 s32 ret = 0;
77
78 if (int_type == V_INT) {
79 vdpo_dev[sel]->int_ctrl.bits.vb_int_en = 1;
80 } else if (int_type == L_INT) {
81 vdpo_dev[sel]->line_int_num.bits.int_line_num = line;
82 vdpo_dev[sel]->int_ctrl.bits.line_match_int_en = 1;
83 } else
84 ret = -1;
85 return ret;
86 }
87
__vdpo_irq_disable(u32 sel,u32 int_type)88 s32 __vdpo_irq_disable(u32 sel, u32 int_type)
89 {
90 s32 ret = 0;
91
92 if (int_type == V_INT)
93 vdpo_dev[sel]->int_ctrl.bits.vb_int_en = 0;
94 else if (int_type == L_INT)
95 vdpo_dev[sel]->int_ctrl.bits.line_match_int_en = 0;
96 else
97 ret = -1;
98 return ret;
99 }
100
__vdpo_irq_process(u32 sel)101 u32 __vdpo_irq_process(u32 sel)
102 {
103 if ((vdpo_dev[sel]->int_ctrl.bits.vb_int_flag) &&
104 (vdpo_dev[sel]->int_ctrl.bits.vb_int_en))
105 return V_INT;
106 else if ((vdpo_dev[sel]->int_ctrl.bits.line_match_int_flag) &&
107 (vdpo_dev[sel]->int_ctrl.bits.line_match_int_en))
108 return L_INT;
109 else
110 return 0;
111 }
112
__vdpo_clr_irq(u32 sel,u32 int_type)113 u32 __vdpo_clr_irq(u32 sel, u32 int_type)
114 {
115 if (int_type == V_INT)
116 vdpo_dev[sel]->int_ctrl.bits.vb_int_flag = 0;
117 else if (int_type == L_INT)
118 vdpo_dev[sel]->int_ctrl.bits.line_match_int_flag = 0;
119 return 0;
120 }
121
__vdpo_timing_set(u32 sel,u32 h_active,u32 h_bp,u32 v_active,u32 v_bp,u32 v_total,u32 interlace,u32 itl_mode)122 void __vdpo_timing_set(u32 sel, u32 h_active, u32 h_bp, u32 v_active, u32 v_bp,
123 u32 v_total, u32 interlace, u32 itl_mode)
124 {
125 vdpo_dev[sel]->h_timing.bits.h_active = h_active - 1;
126 vdpo_dev[sel]->h_timing.bits.h_bp = h_bp - 1;
127 vdpo_dev[sel]->v_timing.bits.v_active = v_active / (interlace + 1) - 1;
128 vdpo_dev[sel]->v_timing.bits.v_bp = v_bp - 1;
129 vdpo_dev[sel]->v_timing1.bits.v_total = v_total * 2 / (interlace + 1);
130 if (interlace)
131 vdpo_dev[sel]->v_timing1.bits.itl_mode = itl_mode;
132 }
133
134 #if 0
135 u32 __vdpo_reg_default_test(u32 sel, u32 addr_offset, u32 exp_value)
136 {
137 u32 base_addr;
138
139 base_addr = VDPO_BASE;
140 if (exp_value != get_wvalue(base_addr + addr_offset))
141 return RET_FAIL;
142 else
143 return RET_OK;
144 }
145
146 u32 __vdpo_reg_wr_test(u32 sel, u32 addr_offset, u32 mask, u32 wr_value)
147 {
148 u32 base_addr, rd_value;
149
150 base_addr = VDPO_BASE;
151 wr_value &= mask;
152 put_wvalue(base_addr + addr_offset, wr_value);
153 rd_value = get_wvalue(base_addr + addr_offset);
154 rd_value &= mask;
155 if (wr_value != rd_value)
156 return RET_FAIL;
157 else
158 return RET_OK;
159 }
160 #endif
161
__vdpo_set_reg_base(u32 sel,void __iomem * base_addr)162 void __vdpo_set_reg_base(u32 sel, void __iomem *base_addr)
163 {
164 vdpo_dev[sel] = (struct __vdpo_dev *)base_addr;
165 }
166