Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
26516 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Analogix DP (Display port) core register interface driver.
4
*
5
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
6
* Author: Jingoo Han <[email protected]>
7
*/
8
9
#include <linux/delay.h>
10
#include <linux/device.h>
11
#include <linux/gpio/consumer.h>
12
#include <linux/io.h>
13
#include <linux/iopoll.h>
14
#include <linux/phy/phy.h>
15
16
#include <drm/bridge/analogix_dp.h>
17
18
#include "analogix_dp_core.h"
19
#include "analogix_dp_reg.h"
20
21
#define COMMON_INT_MASK_1 0
22
#define COMMON_INT_MASK_2 0
23
#define COMMON_INT_MASK_3 0
24
#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
25
#define INT_STA_MASK INT_HPD
26
27
void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable)
28
{
29
u32 reg;
30
31
if (enable) {
32
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
33
reg |= HDCP_VIDEO_MUTE;
34
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
35
} else {
36
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
37
reg &= ~HDCP_VIDEO_MUTE;
38
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
39
}
40
}
41
42
void analogix_dp_stop_video(struct analogix_dp_device *dp)
43
{
44
u32 reg;
45
46
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
47
reg &= ~VIDEO_EN;
48
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
49
}
50
51
void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable)
52
{
53
u32 reg;
54
55
if (enable)
56
reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
57
LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
58
else
59
reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
60
LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
61
62
writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP);
63
}
64
65
void analogix_dp_init_analog_param(struct analogix_dp_device *dp)
66
{
67
u32 reg;
68
69
reg = TX_TERMINAL_CTRL_50_OHM;
70
writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1);
71
72
reg = SEL_24M | TX_DVDD_BIT_1_0625V;
73
writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2);
74
75
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
76
reg = REF_CLK_24M;
77
if (dp->plat_data->dev_type == RK3288_DP)
78
reg ^= REF_CLK_MASK;
79
80
writel(reg, dp->reg_base + ANALOGIX_DP_PLL_REG_1);
81
writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2);
82
writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3);
83
writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4);
84
writel(0x22, dp->reg_base + ANALOGIX_DP_PLL_REG_5);
85
}
86
87
reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
88
writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3);
89
90
reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
91
TX_CUR1_2X | TX_CUR_16_MA;
92
writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1);
93
94
reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
95
CH1_AMP_400_MV | CH0_AMP_400_MV;
96
writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL);
97
}
98
99
void analogix_dp_init_interrupt(struct analogix_dp_device *dp)
100
{
101
/* Set interrupt pin assertion polarity as high */
102
writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL);
103
104
/* Clear pending regisers */
105
writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
106
writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2);
107
writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3);
108
writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
109
writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA);
110
111
/* 0:mask,1: unmask */
112
writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
113
writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
114
writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
115
writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
116
writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
117
}
118
119
void analogix_dp_reset(struct analogix_dp_device *dp)
120
{
121
u32 reg;
122
123
analogix_dp_stop_video(dp);
124
analogix_dp_enable_video_mute(dp, 0);
125
126
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
127
reg = RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N |
128
SW_FUNC_EN_N;
129
else
130
reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
131
AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
132
HDCP_FUNC_EN_N | SW_FUNC_EN_N;
133
134
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
135
136
reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
137
SERDES_FIFO_FUNC_EN_N |
138
LS_CLK_DOMAIN_FUNC_EN_N;
139
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
140
141
usleep_range(20, 30);
142
143
analogix_dp_lane_swap(dp, 0);
144
145
writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
146
writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
147
writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
148
writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
149
150
writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
151
writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL);
152
153
writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
154
writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
155
156
writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL);
157
158
writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST);
159
160
writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD);
161
writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN);
162
163
writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH);
164
writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH);
165
166
writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
167
}
168
169
void analogix_dp_swreset(struct analogix_dp_device *dp)
170
{
171
writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET);
172
}
173
174
void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
175
{
176
u32 reg;
177
178
/* 0: mask, 1: unmask */
179
reg = COMMON_INT_MASK_1;
180
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
181
182
reg = COMMON_INT_MASK_2;
183
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
184
185
reg = COMMON_INT_MASK_3;
186
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
187
188
reg = COMMON_INT_MASK_4;
189
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
190
191
reg = INT_STA_MASK;
192
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
193
}
194
195
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
196
{
197
u32 reg;
198
199
/* 0: mask, 1: unmask */
200
reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
201
reg &= ~COMMON_INT_MASK_4;
202
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
203
204
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
205
reg &= ~INT_STA_MASK;
206
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
207
}
208
209
void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
210
{
211
u32 reg;
212
213
/* 0: mask, 1: unmask */
214
reg = COMMON_INT_MASK_4;
215
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
216
217
reg = INT_STA_MASK;
218
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
219
}
220
221
int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp)
222
{
223
u32 val;
224
225
return readl_poll_timeout(dp->reg_base + ANALOGIX_DP_DEBUG_CTL, val,
226
val & PLL_LOCK, 120,
227
120 * DP_TIMEOUT_LOOP_COUNT);
228
}
229
230
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)
231
{
232
u32 reg;
233
u32 mask = DP_PLL_PD;
234
u32 pd_addr = ANALOGIX_DP_PLL_CTL;
235
236
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
237
pd_addr = ANALOGIX_DP_PD;
238
mask = RK_PLL_PD;
239
}
240
241
reg = readl(dp->reg_base + pd_addr);
242
if (enable)
243
reg |= mask;
244
else
245
reg &= ~mask;
246
writel(reg, dp->reg_base + pd_addr);
247
}
248
249
void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
250
enum analog_power_block block,
251
bool enable)
252
{
253
u32 reg;
254
u32 phy_pd_addr = ANALOGIX_DP_PHY_PD;
255
u32 mask;
256
257
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
258
phy_pd_addr = ANALOGIX_DP_PD;
259
260
switch (block) {
261
case AUX_BLOCK:
262
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
263
mask = RK_AUX_PD;
264
else
265
mask = AUX_PD;
266
267
reg = readl(dp->reg_base + phy_pd_addr);
268
if (enable)
269
reg |= mask;
270
else
271
reg &= ~mask;
272
writel(reg, dp->reg_base + phy_pd_addr);
273
break;
274
case CH0_BLOCK:
275
mask = CH0_PD;
276
reg = readl(dp->reg_base + phy_pd_addr);
277
278
if (enable)
279
reg |= mask;
280
else
281
reg &= ~mask;
282
writel(reg, dp->reg_base + phy_pd_addr);
283
break;
284
case CH1_BLOCK:
285
mask = CH1_PD;
286
reg = readl(dp->reg_base + phy_pd_addr);
287
288
if (enable)
289
reg |= mask;
290
else
291
reg &= ~mask;
292
writel(reg, dp->reg_base + phy_pd_addr);
293
break;
294
case CH2_BLOCK:
295
mask = CH2_PD;
296
reg = readl(dp->reg_base + phy_pd_addr);
297
298
if (enable)
299
reg |= mask;
300
else
301
reg &= ~mask;
302
writel(reg, dp->reg_base + phy_pd_addr);
303
break;
304
case CH3_BLOCK:
305
mask = CH3_PD;
306
reg = readl(dp->reg_base + phy_pd_addr);
307
308
if (enable)
309
reg |= mask;
310
else
311
reg &= ~mask;
312
writel(reg, dp->reg_base + phy_pd_addr);
313
break;
314
case ANALOG_TOTAL:
315
/*
316
* There is no bit named DP_PHY_PD, so We used DP_INC_BG
317
* to power off everything instead of DP_PHY_PD in
318
* Rockchip
319
*/
320
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
321
mask = DP_INC_BG;
322
else
323
mask = DP_PHY_PD;
324
325
reg = readl(dp->reg_base + phy_pd_addr);
326
if (enable)
327
reg |= mask;
328
else
329
reg &= ~mask;
330
331
writel(reg, dp->reg_base + phy_pd_addr);
332
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
333
usleep_range(10, 15);
334
break;
335
case POWER_ALL:
336
if (enable) {
337
reg = DP_ALL_PD;
338
writel(reg, dp->reg_base + phy_pd_addr);
339
} else {
340
reg = DP_ALL_PD;
341
writel(reg, dp->reg_base + phy_pd_addr);
342
usleep_range(10, 15);
343
reg &= ~DP_INC_BG;
344
writel(reg, dp->reg_base + phy_pd_addr);
345
usleep_range(10, 15);
346
347
writel(0x00, dp->reg_base + phy_pd_addr);
348
}
349
break;
350
default:
351
break;
352
}
353
}
354
355
int analogix_dp_init_analog_func(struct analogix_dp_device *dp)
356
{
357
u32 reg;
358
359
analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
360
361
reg = PLL_LOCK_CHG;
362
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
363
364
reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
365
reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
366
writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
367
368
/* Power up PLL */
369
analogix_dp_set_pll_power_down(dp, 0);
370
371
/* Enable Serdes FIFO function and Link symbol clock domain module */
372
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
373
reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
374
| AUX_FUNC_EN_N);
375
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
376
return 0;
377
}
378
379
void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp)
380
{
381
u32 reg;
382
383
if (dp->hpd_gpiod)
384
return;
385
386
reg = HOTPLUG_CHG | HPD_LOST | PLUG;
387
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
388
389
reg = INT_HPD;
390
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);
391
}
392
393
void analogix_dp_init_hpd(struct analogix_dp_device *dp)
394
{
395
u32 reg;
396
397
if (dp->hpd_gpiod)
398
return;
399
400
analogix_dp_clear_hotplug_interrupts(dp);
401
402
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
403
reg &= ~(F_HPD | HPD_CTRL);
404
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
405
}
406
407
void analogix_dp_force_hpd(struct analogix_dp_device *dp)
408
{
409
u32 reg;
410
411
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
412
reg = (F_HPD | HPD_CTRL);
413
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
414
}
415
416
enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
417
{
418
u32 reg;
419
420
if (dp->hpd_gpiod) {
421
reg = gpiod_get_value(dp->hpd_gpiod);
422
if (reg)
423
return DP_IRQ_TYPE_HP_CABLE_IN;
424
else
425
return DP_IRQ_TYPE_HP_CABLE_OUT;
426
} else {
427
/* Parse hotplug interrupt status register */
428
reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
429
430
if (reg & PLUG)
431
return DP_IRQ_TYPE_HP_CABLE_IN;
432
433
if (reg & HPD_LOST)
434
return DP_IRQ_TYPE_HP_CABLE_OUT;
435
436
if (reg & HOTPLUG_CHG)
437
return DP_IRQ_TYPE_HP_CHANGE;
438
439
return DP_IRQ_TYPE_UNKNOWN;
440
}
441
}
442
443
void analogix_dp_reset_aux(struct analogix_dp_device *dp)
444
{
445
u32 reg;
446
447
/* Disable AUX channel module */
448
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
449
reg |= AUX_FUNC_EN_N;
450
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
451
}
452
453
void analogix_dp_init_aux(struct analogix_dp_device *dp)
454
{
455
u32 reg;
456
457
/* Clear inerrupts related to AUX channel */
458
reg = RPLY_RECEIV | AUX_ERR;
459
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);
460
461
analogix_dp_set_analog_power_down(dp, AUX_BLOCK, true);
462
usleep_range(10, 11);
463
analogix_dp_set_analog_power_down(dp, AUX_BLOCK, false);
464
465
analogix_dp_reset_aux(dp);
466
467
/* AUX_BIT_PERIOD_EXPECTED_DELAY doesn't apply to Rockchip IP */
468
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
469
reg = 0;
470
else
471
reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3);
472
473
/* Disable AUX transaction H/W retry */
474
reg |= AUX_HW_RETRY_COUNT_SEL(0) |
475
AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
476
477
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL);
478
479
/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
480
reg = DEFER_CTRL_EN | DEFER_COUNT(1);
481
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL);
482
483
/* Enable AUX channel module */
484
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
485
reg &= ~AUX_FUNC_EN_N;
486
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
487
}
488
489
int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp)
490
{
491
u32 reg;
492
493
if (dp->hpd_gpiod) {
494
if (gpiod_get_value(dp->hpd_gpiod))
495
return 0;
496
} else {
497
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
498
if (reg & HPD_STATUS)
499
return 0;
500
}
501
502
return -EINVAL;
503
}
504
505
void analogix_dp_enable_sw_function(struct analogix_dp_device *dp)
506
{
507
u32 reg;
508
509
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
510
reg &= ~SW_FUNC_EN_N;
511
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
512
}
513
514
void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
515
{
516
u32 reg;
517
int ret;
518
519
reg = bwtype;
520
if ((bwtype == DP_LINK_BW_2_7) || (bwtype == DP_LINK_BW_1_62))
521
writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET);
522
523
if (dp->phy) {
524
union phy_configure_opts phy_cfg = {0};
525
526
phy_cfg.dp.link_rate =
527
drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
528
phy_cfg.dp.set_rate = true;
529
ret = phy_configure(dp->phy, &phy_cfg);
530
if (ret && ret != -EOPNOTSUPP) {
531
dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
532
return;
533
}
534
}
535
}
536
537
void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
538
{
539
u32 reg;
540
541
reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET);
542
*bwtype = reg;
543
}
544
545
void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)
546
{
547
u32 reg;
548
int ret;
549
550
reg = count;
551
writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);
552
553
if (dp->phy) {
554
union phy_configure_opts phy_cfg = {0};
555
556
phy_cfg.dp.lanes = dp->link_train.lane_count;
557
phy_cfg.dp.set_lanes = true;
558
ret = phy_configure(dp->phy, &phy_cfg);
559
if (ret && ret != -EOPNOTSUPP) {
560
dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
561
return;
562
}
563
}
564
}
565
566
void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
567
{
568
u32 reg;
569
570
reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);
571
*count = reg;
572
}
573
574
void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)
575
{
576
u8 lane;
577
int ret;
578
579
for (lane = 0; lane < dp->link_train.lane_count; lane++)
580
writel(dp->link_train.training_lane[lane],
581
dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
582
583
if (dp->phy) {
584
union phy_configure_opts phy_cfg = {0};
585
586
for (lane = 0; lane < dp->link_train.lane_count; lane++) {
587
u8 training_lane = dp->link_train.training_lane[lane];
588
u8 vs, pe;
589
590
vs = (training_lane & DP_TRAIN_VOLTAGE_SWING_MASK) >>
591
DP_TRAIN_VOLTAGE_SWING_SHIFT;
592
pe = (training_lane & DP_TRAIN_PRE_EMPHASIS_MASK) >>
593
DP_TRAIN_PRE_EMPHASIS_SHIFT;
594
phy_cfg.dp.voltage[lane] = vs;
595
phy_cfg.dp.pre[lane] = pe;
596
}
597
598
phy_cfg.dp.set_voltages = true;
599
ret = phy_configure(dp->phy, &phy_cfg);
600
if (ret && ret != -EOPNOTSUPP) {
601
dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
602
return;
603
}
604
}
605
}
606
607
u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)
608
{
609
return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
610
}
611
612
void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
613
bool enable)
614
{
615
u32 reg;
616
617
if (enable) {
618
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
619
reg |= ENHANCED;
620
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
621
} else {
622
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
623
reg &= ~ENHANCED;
624
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
625
}
626
}
627
628
void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
629
enum pattern_set pattern)
630
{
631
u32 reg;
632
633
switch (pattern) {
634
case PRBS7:
635
reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
636
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
637
break;
638
case D10_2:
639
reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
640
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
641
break;
642
case TRAINING_PTN1:
643
reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
644
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
645
break;
646
case TRAINING_PTN2:
647
reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
648
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
649
break;
650
case DP_NONE:
651
reg = SCRAMBLING_ENABLE |
652
LINK_QUAL_PATTERN_SET_DISABLE |
653
SW_TRAINING_PATTERN_SET_NORMAL;
654
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
655
break;
656
default:
657
break;
658
}
659
}
660
661
void analogix_dp_reset_macro(struct analogix_dp_device *dp)
662
{
663
u32 reg;
664
665
reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST);
666
reg |= MACRO_RST;
667
writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);
668
669
/* 10 us is the minimum reset time. */
670
usleep_range(10, 20);
671
672
reg &= ~MACRO_RST;
673
writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);
674
}
675
676
void analogix_dp_init_video(struct analogix_dp_device *dp)
677
{
678
u32 reg;
679
680
reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
681
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
682
683
reg = 0x0;
684
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
685
686
reg = CHA_CRI(4) | CHA_CTRL;
687
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
688
689
reg = 0x0;
690
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
691
692
reg = VID_HRES_TH(2) | VID_VRES_TH(0);
693
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8);
694
}
695
696
void analogix_dp_set_video_color_format(struct analogix_dp_device *dp)
697
{
698
u32 reg;
699
700
/* Configure the input color depth, color space, dynamic range */
701
reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) |
702
(dp->video_info.color_depth << IN_BPC_SHIFT) |
703
(dp->video_info.color_space << IN_COLOR_F_SHIFT);
704
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2);
705
706
/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
707
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
708
reg &= ~IN_YC_COEFFI_MASK;
709
if (dp->video_info.ycbcr_coeff)
710
reg |= IN_YC_COEFFI_ITU709;
711
else
712
reg |= IN_YC_COEFFI_ITU601;
713
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
714
}
715
716
int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp)
717
{
718
u32 reg;
719
720
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
721
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
722
723
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
724
725
if (!(reg & DET_STA)) {
726
dev_dbg(dp->dev, "Input stream clock not detected.\n");
727
return -EINVAL;
728
}
729
730
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
731
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
732
733
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
734
dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
735
736
if (reg & CHA_STA) {
737
dev_dbg(dp->dev, "Input stream clk is changing\n");
738
return -EINVAL;
739
}
740
741
return 0;
742
}
743
744
void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
745
enum clock_recovery_m_value_type type,
746
u32 m_value, u32 n_value)
747
{
748
u32 reg;
749
750
if (type == REGISTER_M) {
751
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
752
reg |= FIX_M_VID;
753
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
754
reg = m_value & 0xff;
755
writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0);
756
reg = (m_value >> 8) & 0xff;
757
writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1);
758
reg = (m_value >> 16) & 0xff;
759
writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2);
760
761
reg = n_value & 0xff;
762
writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0);
763
reg = (n_value >> 8) & 0xff;
764
writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1);
765
reg = (n_value >> 16) & 0xff;
766
writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2);
767
} else {
768
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
769
reg &= ~FIX_M_VID;
770
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
771
772
writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0);
773
writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1);
774
writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2);
775
}
776
}
777
778
void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type)
779
{
780
u32 reg;
781
782
if (type == VIDEO_TIMING_FROM_CAPTURE) {
783
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
784
reg &= ~FORMAT_SEL;
785
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
786
} else {
787
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
788
reg |= FORMAT_SEL;
789
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
790
}
791
}
792
793
void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable)
794
{
795
u32 reg;
796
797
if (enable) {
798
reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
799
reg &= ~VIDEO_MODE_MASK;
800
reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
801
writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
802
} else {
803
reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
804
reg &= ~VIDEO_MODE_MASK;
805
reg |= VIDEO_MODE_SLAVE_MODE;
806
writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
807
}
808
}
809
810
void analogix_dp_start_video(struct analogix_dp_device *dp)
811
{
812
u32 reg;
813
814
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
815
reg |= VIDEO_EN;
816
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
817
}
818
819
int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)
820
{
821
u32 reg;
822
823
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
824
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
825
826
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
827
if (!(reg & STRM_VALID)) {
828
dev_dbg(dp->dev, "Input video stream is not detected.\n");
829
return -EINVAL;
830
}
831
832
return 0;
833
}
834
835
void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)
836
{
837
u32 reg;
838
839
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
840
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
841
reg &= ~(RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N);
842
} else {
843
reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
844
reg |= MASTER_VID_FUNC_EN_N;
845
}
846
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
847
848
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
849
reg &= ~INTERACE_SCAN_CFG;
850
reg |= (dp->video_info.interlaced << 2);
851
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
852
853
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
854
reg &= ~VSYNC_POLARITY_CFG;
855
reg |= (dp->video_info.v_sync_polarity << 1);
856
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
857
858
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
859
reg &= ~HSYNC_POLARITY_CFG;
860
reg |= (dp->video_info.h_sync_polarity << 0);
861
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
862
863
reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
864
writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
865
}
866
867
void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)
868
{
869
u32 reg;
870
871
reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
872
reg &= ~SCRAMBLING_DISABLE;
873
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
874
}
875
876
void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
877
{
878
u32 reg;
879
880
reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
881
reg |= SCRAMBLING_DISABLE;
882
writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
883
}
884
885
void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp)
886
{
887
writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
888
}
889
890
static ssize_t analogix_dp_get_psr_status(struct analogix_dp_device *dp)
891
{
892
ssize_t val;
893
u8 status;
894
895
val = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &status);
896
if (val < 0) {
897
dev_err(dp->dev, "PSR_STATUS read failed ret=%zd", val);
898
return val;
899
}
900
return status;
901
}
902
903
int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
904
struct dp_sdp *vsc, bool blocking)
905
{
906
unsigned int val;
907
int ret;
908
ssize_t psr_status;
909
910
/* don't send info frame */
911
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
912
val &= ~IF_EN;
913
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
914
915
/* configure single frame update mode */
916
writel(PSR_FRAME_UP_TYPE_BURST | PSR_CRC_SEL_HARDWARE,
917
dp->reg_base + ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL);
918
919
/* configure VSC HB0~HB3 */
920
writel(vsc->sdp_header.HB0, dp->reg_base + ANALOGIX_DP_SPD_HB0);
921
writel(vsc->sdp_header.HB1, dp->reg_base + ANALOGIX_DP_SPD_HB1);
922
writel(vsc->sdp_header.HB2, dp->reg_base + ANALOGIX_DP_SPD_HB2);
923
writel(vsc->sdp_header.HB3, dp->reg_base + ANALOGIX_DP_SPD_HB3);
924
925
/* configure reused VSC PB0~PB3, magic number from vendor */
926
writel(0x00, dp->reg_base + ANALOGIX_DP_SPD_PB0);
927
writel(0x16, dp->reg_base + ANALOGIX_DP_SPD_PB1);
928
writel(0xCE, dp->reg_base + ANALOGIX_DP_SPD_PB2);
929
writel(0x5D, dp->reg_base + ANALOGIX_DP_SPD_PB3);
930
931
/* configure DB0 / DB1 values */
932
writel(vsc->db[0], dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB0);
933
writel(vsc->db[1], dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB1);
934
935
/* set reuse spd inforframe */
936
val = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
937
val |= REUSE_SPD_EN;
938
writel(val, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
939
940
/* mark info frame update */
941
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
942
val = (val | IF_UP) & ~IF_EN;
943
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
944
945
/* send info frame */
946
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
947
val |= IF_EN;
948
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
949
950
if (!blocking)
951
return 0;
952
953
/*
954
* db[1]!=0: entering PSR, wait for fully active remote frame buffer.
955
* db[1]==0: exiting PSR, wait for either
956
* (a) ACTIVE_RESYNC - the sink "must display the
957
* incoming active frames from the Source device with no visible
958
* glitches and/or artifacts", even though timings may still be
959
* re-synchronizing; or
960
* (b) INACTIVE - the transition is fully complete.
961
*/
962
ret = readx_poll_timeout(analogix_dp_get_psr_status, dp, psr_status,
963
psr_status >= 0 &&
964
((vsc->db[1] && psr_status == DP_PSR_SINK_ACTIVE_RFB) ||
965
(!vsc->db[1] && (psr_status == DP_PSR_SINK_ACTIVE_RESYNC ||
966
psr_status == DP_PSR_SINK_INACTIVE))),
967
1500, DP_TIMEOUT_PSR_LOOP_MS * 1000);
968
if (ret) {
969
dev_warn(dp->dev, "Failed to apply PSR %d\n", ret);
970
return ret;
971
}
972
return 0;
973
}
974
975
ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
976
struct drm_dp_aux_msg *msg)
977
{
978
u32 reg;
979
u8 *buffer = msg->buffer;
980
unsigned int i;
981
int ret;
982
983
/* Buffer size of AUX CH is 16 bytes */
984
if (WARN_ON(msg->size > 16))
985
return -E2BIG;
986
987
/* Clear AUX CH data buffer */
988
reg = BUF_CLR;
989
writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
990
991
switch (msg->request & ~DP_AUX_I2C_MOT) {
992
case DP_AUX_I2C_WRITE:
993
reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_I2C_TRANSACTION;
994
if (msg->request & DP_AUX_I2C_MOT)
995
reg |= AUX_TX_COMM_MOT;
996
break;
997
998
case DP_AUX_I2C_READ:
999
reg = AUX_TX_COMM_READ | AUX_TX_COMM_I2C_TRANSACTION;
1000
if (msg->request & DP_AUX_I2C_MOT)
1001
reg |= AUX_TX_COMM_MOT;
1002
break;
1003
1004
case DP_AUX_NATIVE_WRITE:
1005
reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_DP_TRANSACTION;
1006
break;
1007
1008
case DP_AUX_NATIVE_READ:
1009
reg = AUX_TX_COMM_READ | AUX_TX_COMM_DP_TRANSACTION;
1010
break;
1011
1012
default:
1013
return -EINVAL;
1014
}
1015
1016
reg |= AUX_LENGTH(msg->size);
1017
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
1018
1019
/* Select DPCD device address */
1020
reg = AUX_ADDR_7_0(msg->address);
1021
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
1022
reg = AUX_ADDR_15_8(msg->address);
1023
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
1024
reg = AUX_ADDR_19_16(msg->address);
1025
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
1026
1027
if (!(msg->request & DP_AUX_I2C_READ)) {
1028
for (i = 0; i < msg->size; i++) {
1029
reg = buffer[i];
1030
writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
1031
4 * i);
1032
}
1033
}
1034
1035
/* Enable AUX CH operation */
1036
reg = AUX_EN;
1037
1038
/* Zero-sized messages specify address-only transactions. */
1039
if (msg->size < 1)
1040
reg |= ADDR_ONLY;
1041
1042
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
1043
1044
ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2,
1045
reg, !(reg & AUX_EN), 25, 500 * 1000);
1046
if (ret) {
1047
dev_err(dp->dev, "AUX CH enable timeout!\n");
1048
goto aux_error;
1049
}
1050
1051
/* TODO: Wait for an interrupt instead of looping? */
1052
/* Is AUX CH command reply received? */
1053
ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_INT_STA,
1054
reg, reg & RPLY_RECEIV, 10, 20 * 1000);
1055
if (ret) {
1056
dev_err(dp->dev, "AUX CH cmd reply timeout!\n");
1057
goto aux_error;
1058
}
1059
1060
/* Clear interrupt source for AUX CH command reply */
1061
writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA);
1062
1063
/* Clear interrupt source for AUX CH access error */
1064
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
1065
if ((reg & AUX_ERR)) {
1066
u32 aux_status = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA) &
1067
AUX_STATUS_MASK;
1068
1069
writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);
1070
1071
if (aux_status == AUX_STATUS_TIMEOUT_ERROR)
1072
return -ETIMEDOUT;
1073
1074
dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n",
1075
aux_status, !!(reg & AUX_ERR));
1076
goto aux_error;
1077
}
1078
1079
if (msg->request & DP_AUX_I2C_READ) {
1080
for (i = 0; i < msg->size; i++) {
1081
reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
1082
4 * i);
1083
buffer[i] = (unsigned char)reg;
1084
}
1085
}
1086
1087
/* Check if Rx sends defer */
1088
reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM);
1089
if (reg == AUX_RX_COMM_AUX_DEFER)
1090
msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
1091
else if (reg == AUX_RX_COMM_I2C_DEFER)
1092
msg->reply = DP_AUX_I2C_REPLY_DEFER;
1093
else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE ||
1094
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_READ)
1095
msg->reply = DP_AUX_I2C_REPLY_ACK;
1096
else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE ||
1097
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
1098
msg->reply = DP_AUX_NATIVE_REPLY_ACK;
1099
1100
return msg->size;
1101
1102
aux_error:
1103
/* if aux err happen, reset aux */
1104
analogix_dp_init_aux(dp);
1105
1106
return -EREMOTEIO;
1107
}
1108
1109