Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/ast/ast_dp501.c
26493 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
#include <linux/delay.h>
4
#include <linux/firmware.h>
5
#include <linux/module.h>
6
7
#include <drm/drm_atomic_state_helper.h>
8
#include <drm/drm_edid.h>
9
#include <drm/drm_modeset_helper_vtables.h>
10
#include <drm/drm_probe_helper.h>
11
12
#include "ast_drv.h"
13
14
MODULE_FIRMWARE("ast_dp501_fw.bin");
15
16
static void ast_release_firmware(void *data)
17
{
18
struct ast_device *ast = data;
19
20
release_firmware(ast->dp501_fw);
21
ast->dp501_fw = NULL;
22
}
23
24
static int ast_load_dp501_microcode(struct ast_device *ast)
25
{
26
struct drm_device *dev = &ast->base;
27
int ret;
28
29
ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev);
30
if (ret)
31
return ret;
32
33
return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast);
34
}
35
36
static void send_ack(struct ast_device *ast)
37
{
38
u8 sendack;
39
sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff);
40
sendack |= 0x80;
41
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack);
42
}
43
44
static void send_nack(struct ast_device *ast)
45
{
46
u8 sendack;
47
sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff);
48
sendack &= ~0x80;
49
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack);
50
}
51
52
static bool wait_ack(struct ast_device *ast)
53
{
54
u8 waitack;
55
u32 retry = 0;
56
do {
57
waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);
58
waitack &= 0x80;
59
udelay(100);
60
} while ((!waitack) && (retry++ < 1000));
61
62
if (retry < 1000)
63
return true;
64
else
65
return false;
66
}
67
68
static bool wait_nack(struct ast_device *ast)
69
{
70
u8 waitack;
71
u32 retry = 0;
72
do {
73
waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);
74
waitack &= 0x80;
75
udelay(100);
76
} while ((waitack) && (retry++ < 1000));
77
78
if (retry < 1000)
79
return true;
80
else
81
return false;
82
}
83
84
static void set_cmd_trigger(struct ast_device *ast)
85
{
86
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x40);
87
}
88
89
static void clear_cmd_trigger(struct ast_device *ast)
90
{
91
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x00);
92
}
93
94
#if 0
95
static bool wait_fw_ready(struct ast_device *ast)
96
{
97
u8 waitready;
98
u32 retry = 0;
99
do {
100
waitready = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);
101
waitready &= 0x40;
102
udelay(100);
103
} while ((!waitready) && (retry++ < 1000));
104
105
if (retry < 1000)
106
return true;
107
else
108
return false;
109
}
110
#endif
111
112
static bool ast_write_cmd(struct ast_device *ast, u8 data)
113
{
114
int retry = 0;
115
116
if (wait_nack(ast)) {
117
send_nack(ast);
118
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data);
119
send_ack(ast);
120
set_cmd_trigger(ast);
121
do {
122
if (wait_ack(ast)) {
123
clear_cmd_trigger(ast);
124
send_nack(ast);
125
return true;
126
}
127
} while (retry++ < 100);
128
}
129
clear_cmd_trigger(ast);
130
send_nack(ast);
131
return false;
132
}
133
134
static bool ast_write_data(struct ast_device *ast, u8 data)
135
{
136
if (wait_nack(ast)) {
137
send_nack(ast);
138
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data);
139
send_ack(ast);
140
if (wait_ack(ast)) {
141
send_nack(ast);
142
return true;
143
}
144
}
145
send_nack(ast);
146
return false;
147
}
148
149
#if 0
150
static bool ast_read_data(struct drm_device *dev, u8 *data)
151
{
152
struct ast_device *ast = to_ast_device(dev);
153
u8 tmp;
154
155
*data = 0;
156
157
if (wait_ack(ast) == false)
158
return false;
159
tmp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd3, 0xff);
160
*data = tmp;
161
if (wait_nack(ast) == false) {
162
send_nack(ast);
163
return false;
164
}
165
send_nack(ast);
166
return true;
167
}
168
169
static void clear_cmd(struct ast_device *ast)
170
{
171
send_nack(ast);
172
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, 0x00);
173
}
174
#endif
175
176
static void ast_set_dp501_video_output(struct ast_device *ast, u8 mode)
177
{
178
ast_write_cmd(ast, 0x40);
179
ast_write_data(ast, mode);
180
181
msleep(10);
182
}
183
184
static u32 get_fw_base(struct ast_device *ast)
185
{
186
return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
187
}
188
189
bool ast_backup_fw(struct ast_device *ast, u8 *addr, u32 size)
190
{
191
u32 i, data;
192
u32 boot_address;
193
194
if (ast->config_mode != ast_use_p2a)
195
return false;
196
197
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
198
if (data) {
199
boot_address = get_fw_base(ast);
200
for (i = 0; i < size; i += 4)
201
*(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
202
return true;
203
}
204
return false;
205
}
206
207
static bool ast_launch_m68k(struct ast_device *ast)
208
{
209
u32 i, data, len = 0;
210
u32 boot_address;
211
u8 *fw_addr = NULL;
212
u8 jreg;
213
214
if (ast->config_mode != ast_use_p2a)
215
return false;
216
217
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
218
if (!data) {
219
220
if (ast->dp501_fw_addr) {
221
fw_addr = ast->dp501_fw_addr;
222
len = 32*1024;
223
} else {
224
if (!ast->dp501_fw &&
225
ast_load_dp501_microcode(ast) < 0)
226
return false;
227
228
fw_addr = (u8 *)ast->dp501_fw->data;
229
len = ast->dp501_fw->size;
230
}
231
/* Get BootAddress */
232
ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
233
data = ast_mindwm(ast, 0x1e6e0004);
234
switch (data & 0x03) {
235
case 0:
236
boot_address = 0x44000000;
237
break;
238
default:
239
case 1:
240
boot_address = 0x48000000;
241
break;
242
case 2:
243
boot_address = 0x50000000;
244
break;
245
case 3:
246
boot_address = 0x60000000;
247
break;
248
}
249
boot_address -= 0x200000; /* -2MB */
250
251
/* copy image to buffer */
252
for (i = 0; i < len; i += 4) {
253
data = *(u32 *)(fw_addr + i);
254
ast_moutdwm(ast, boot_address + i, data);
255
}
256
257
/* Init SCU */
258
ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
259
260
/* Launch FW */
261
ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
262
ast_moutdwm(ast, 0x1e6e2100, 1);
263
264
/* Update Scratch */
265
data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff; /* D[11:9] = 100b: UEFI handling */
266
data |= 0x800;
267
ast_moutdwm(ast, 0x1e6e2040, data);
268
269
jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */
270
jreg |= 0x02;
271
ast_set_index_reg(ast, AST_IO_VGACRI, 0x99, jreg);
272
}
273
return true;
274
}
275
276
static bool ast_dp501_is_connected(struct ast_device *ast)
277
{
278
u32 boot_address, offset, data;
279
280
if (ast->config_mode == ast_use_p2a) {
281
boot_address = get_fw_base(ast);
282
283
/* validate FW version */
284
offset = AST_DP501_GBL_VERSION;
285
data = ast_mindwm(ast, boot_address + offset);
286
if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
287
return false;
288
289
/* validate PnP Monitor */
290
offset = AST_DP501_PNPMONITOR;
291
data = ast_mindwm(ast, boot_address + offset);
292
if (!(data & AST_DP501_PNP_CONNECTED))
293
return false;
294
} else {
295
if (!ast->dp501_fw_buf)
296
return false;
297
298
/* dummy read */
299
offset = 0x0000;
300
data = readl(ast->dp501_fw_buf + offset);
301
302
/* validate FW version */
303
offset = AST_DP501_GBL_VERSION;
304
data = readl(ast->dp501_fw_buf + offset);
305
if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
306
return false;
307
308
/* validate PnP Monitor */
309
offset = AST_DP501_PNPMONITOR;
310
data = readl(ast->dp501_fw_buf + offset);
311
if (!(data & AST_DP501_PNP_CONNECTED))
312
return false;
313
}
314
return true;
315
}
316
317
static int ast_dp512_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
318
{
319
struct ast_device *ast = data;
320
size_t rdlen = round_up(len, 4);
321
u32 i, boot_address, offset, ediddata;
322
323
if (block > (512 / EDID_LENGTH))
324
return -EIO;
325
326
offset = AST_DP501_EDID_DATA + block * EDID_LENGTH;
327
328
if (ast->config_mode == ast_use_p2a) {
329
boot_address = get_fw_base(ast);
330
331
for (i = 0; i < rdlen; i += 4) {
332
ediddata = ast_mindwm(ast, boot_address + offset + i);
333
memcpy(buf, &ediddata, min((len - i), 4));
334
buf += 4;
335
}
336
} else {
337
for (i = 0; i < rdlen; i += 4) {
338
ediddata = readl(ast->dp501_fw_buf + offset + i);
339
memcpy(buf, &ediddata, min((len - i), 4));
340
buf += 4;
341
}
342
}
343
344
return true;
345
}
346
347
static bool ast_init_dvo(struct ast_device *ast)
348
{
349
u8 jreg;
350
u32 data;
351
ast_write32(ast, 0xf004, 0x1e6e0000);
352
ast_write32(ast, 0xf000, 0x1);
353
ast_write32(ast, 0x12000, 0x1688a8a8);
354
355
jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
356
if (!(jreg & 0x80)) {
357
/* Init SCU DVO Settings */
358
data = ast_read32(ast, 0x12008);
359
/* delay phase */
360
data &= 0xfffff8ff;
361
data |= 0x00000500;
362
ast_write32(ast, 0x12008, data);
363
364
if (IS_AST_GEN4(ast)) {
365
data = ast_read32(ast, 0x12084);
366
/* multi-pins for DVO single-edge */
367
data |= 0xfffe0000;
368
ast_write32(ast, 0x12084, data);
369
370
data = ast_read32(ast, 0x12088);
371
/* multi-pins for DVO single-edge */
372
data |= 0x000fffff;
373
ast_write32(ast, 0x12088, data);
374
375
data = ast_read32(ast, 0x12090);
376
/* multi-pins for DVO single-edge */
377
data &= 0xffffffcf;
378
data |= 0x00000020;
379
ast_write32(ast, 0x12090, data);
380
} else { /* AST GEN5+ */
381
data = ast_read32(ast, 0x12088);
382
/* multi-pins for DVO single-edge */
383
data |= 0x30000000;
384
ast_write32(ast, 0x12088, data);
385
386
data = ast_read32(ast, 0x1208c);
387
/* multi-pins for DVO single-edge */
388
data |= 0x000000cf;
389
ast_write32(ast, 0x1208c, data);
390
391
data = ast_read32(ast, 0x120a4);
392
/* multi-pins for DVO single-edge */
393
data |= 0xffff0000;
394
ast_write32(ast, 0x120a4, data);
395
396
data = ast_read32(ast, 0x120a8);
397
/* multi-pins for DVO single-edge */
398
data |= 0x0000000f;
399
ast_write32(ast, 0x120a8, data);
400
401
data = ast_read32(ast, 0x12094);
402
/* multi-pins for DVO single-edge */
403
data |= 0x00000002;
404
ast_write32(ast, 0x12094, data);
405
}
406
}
407
408
/* Force to DVO */
409
data = ast_read32(ast, 0x1202c);
410
data &= 0xfffbffff;
411
ast_write32(ast, 0x1202c, data);
412
413
/* Init VGA DVO Settings */
414
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
415
return true;
416
}
417
418
419
static void ast_init_analog(struct ast_device *ast)
420
{
421
u32 data;
422
423
/*
424
* Set DAC source to VGA mode in SCU2C via the P2A
425
* bridge. First configure the P2U to target the SCU
426
* in case it isn't at this stage.
427
*/
428
ast_write32(ast, 0xf004, 0x1e6e0000);
429
ast_write32(ast, 0xf000, 0x1);
430
431
/* Then unlock the SCU with the magic password */
432
ast_write32(ast, 0x12000, 0x1688a8a8);
433
ast_write32(ast, 0x12000, 0x1688a8a8);
434
ast_write32(ast, 0x12000, 0x1688a8a8);
435
436
/* Finally, clear bits [17:16] of SCU2c */
437
data = ast_read32(ast, 0x1202c);
438
data &= 0xfffcffff;
439
ast_write32(ast, 0, data);
440
441
/* Disable DVO */
442
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);
443
}
444
445
void ast_init_3rdtx(struct ast_device *ast)
446
{
447
u8 vgacrd1;
448
449
if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {
450
vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1,
451
AST_IO_VGACRD1_TX_TYPE_MASK);
452
switch (vgacrd1) {
453
case AST_IO_VGACRD1_TX_SIL164_VBIOS:
454
ast_init_dvo(ast);
455
break;
456
case AST_IO_VGACRD1_TX_DP501_VBIOS:
457
ast_launch_m68k(ast);
458
break;
459
case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW:
460
ast_init_dvo(ast);
461
break;
462
default:
463
if (ast->tx_chip == AST_TX_SIL164)
464
ast_init_dvo(ast);
465
else
466
ast_init_analog(ast);
467
}
468
}
469
}
470
471
/*
472
* Encoder
473
*/
474
475
static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {
476
.destroy = drm_encoder_cleanup,
477
};
478
479
static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,
480
struct drm_atomic_state *state)
481
{
482
struct ast_device *ast = to_ast_device(encoder->dev);
483
484
ast_set_dp501_video_output(ast, 1);
485
}
486
487
static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,
488
struct drm_atomic_state *state)
489
{
490
struct ast_device *ast = to_ast_device(encoder->dev);
491
492
ast_set_dp501_video_output(ast, 0);
493
}
494
495
static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {
496
.atomic_enable = ast_dp501_encoder_helper_atomic_enable,
497
.atomic_disable = ast_dp501_encoder_helper_atomic_disable,
498
};
499
500
/*
501
* Connector
502
*/
503
504
static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
505
{
506
struct ast_connector *ast_connector = to_ast_connector(connector);
507
int count;
508
509
if (ast_connector->physical_status == connector_status_connected) {
510
struct ast_device *ast = to_ast_device(connector->dev);
511
const struct drm_edid *drm_edid;
512
513
drm_edid = drm_edid_read_custom(connector, ast_dp512_read_edid_block, ast);
514
drm_edid_connector_update(connector, drm_edid);
515
count = drm_edid_connector_add_modes(connector);
516
drm_edid_free(drm_edid);
517
} else {
518
drm_edid_connector_update(connector, NULL);
519
520
/*
521
* There's no EDID data without a connected monitor. Set BMC-
522
* compatible modes in this case. The XGA default resolution
523
* should work well for all BMCs.
524
*/
525
count = drm_add_modes_noedid(connector, 4096, 4096);
526
if (count)
527
drm_set_preferred_mode(connector, 1024, 768);
528
}
529
530
return count;
531
}
532
533
static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,
534
struct drm_modeset_acquire_ctx *ctx,
535
bool force)
536
{
537
struct ast_connector *ast_connector = to_ast_connector(connector);
538
struct ast_device *ast = to_ast_device(connector->dev);
539
enum drm_connector_status status = connector_status_disconnected;
540
541
if (ast_dp501_is_connected(ast))
542
status = connector_status_connected;
543
544
if (status != ast_connector->physical_status)
545
++connector->epoch_counter;
546
ast_connector->physical_status = status;
547
548
return connector_status_connected;
549
}
550
551
static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
552
.get_modes = ast_dp501_connector_helper_get_modes,
553
.detect_ctx = ast_dp501_connector_helper_detect_ctx,
554
};
555
556
static const struct drm_connector_funcs ast_dp501_connector_funcs = {
557
.reset = drm_atomic_helper_connector_reset,
558
.fill_modes = drm_helper_probe_single_connector_modes,
559
.destroy = drm_connector_cleanup,
560
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
561
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
562
};
563
564
/*
565
* Output
566
*/
567
568
int ast_dp501_output_init(struct ast_device *ast)
569
{
570
struct drm_device *dev = &ast->base;
571
struct drm_crtc *crtc = &ast->crtc;
572
struct drm_encoder *encoder;
573
struct ast_connector *ast_connector;
574
struct drm_connector *connector;
575
int ret;
576
577
/* encoder */
578
579
encoder = &ast->output.dp501.encoder;
580
ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs,
581
DRM_MODE_ENCODER_TMDS, NULL);
582
if (ret)
583
return ret;
584
drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);
585
586
encoder->possible_crtcs = drm_crtc_mask(crtc);
587
588
/* connector */
589
590
ast_connector = &ast->output.dp501.connector;
591
connector = &ast_connector->base;
592
ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
593
DRM_MODE_CONNECTOR_DisplayPort);
594
if (ret)
595
return ret;
596
drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
597
598
connector->interlace_allowed = 0;
599
connector->doublescan_allowed = 0;
600
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
601
602
ast_connector->physical_status = connector->status;
603
604
ret = drm_connector_attach_encoder(connector, encoder);
605
if (ret)
606
return ret;
607
608
return 0;
609
}
610
611