1/*
2 * Copyright (c) 2018 Loongson Technology Co., Ltd.
3 * Authors:
4 *	Chen Zhu <zhuchen@loongson.cn>
5 *	Yaling Fang <fangyaling@loongson.cn>
6 *	Dandan Zhang <zhangdandan@loongson.cn>
7 *	Huacai Chen <chenhc@lemote.com>
8 * This program is free software; you can redistribute  it and/or modify it
9 * under  the terms of  the GNU General  Public License as published by the
10 * Free Software Foundation;  either version 2 of the  License, or (at your
11 * option) any later version.
12 */
13
14#include "loongson_drv.h"
15#include "loongson_vbios.h"
16
17#define VBIOS_START 0x1000
18#define VBIOS_SIZE  0x40000
19#define VBIOS_OFFSET 0x100000
20#define VBIOS_DESC_OFFSET 0x6000
21#define VBIOS_TITLE "Loongson-VBIOS"
22
23/* VBIOS INFO ADDRESS TABLE */
24struct acpi_viat_table {
25	struct acpi_table_header header;
26	unsigned long vbios_addr;
27} __packed;
28
29static u32 get_vbios_version(struct loongson_vbios *vbios)
30{
31	u32 minor, major, version;
32
33	minor = vbios->version_minor;
34	major = vbios->version_major;
35	version = major * 10 + minor;
36
37	return version;
38}
39
40static bool parse_vbios_i2c(struct desc_node *this, struct vbios_cmd *cmd)
41{
42	bool ret = true;
43	int i, num, size;
44	struct vbios_i2c *i2c;
45	struct vbios_i2c *vbios_i2c = NULL;
46	struct loongson_i2c *val = (struct loongson_i2c *)cmd->res;
47
48	size = this->desc->size;
49	vbios_i2c = kzalloc(size, GFP_KERNEL);
50	if (!vbios_i2c)
51		return false;
52
53	memset(vbios_i2c, 0xff, size);
54	memcpy(vbios_i2c, this->data, size);
55	num = size / sizeof(*vbios_i2c);
56
57	i2c = vbios_i2c;
58	for (i = 0; (i < num && i < DC_I2C_BUS_MAX); i++) {
59		val->i2c_id = (u32)i2c->id;
60		val->use = true;
61		val++;
62		i2c++;
63	}
64
65	kfree(vbios_i2c);
66	return ret;
67}
68
69static bool parse_vbios_crtc(struct desc_node *this, struct vbios_cmd *cmd)
70{
71	bool ret = true;
72	u64 request = (u64)cmd->req;
73	u32 *val = (u32 *)cmd->res;
74	struct vbios_crtc crtc;
75
76	memset(&crtc, 0xff, sizeof(crtc));
77	memcpy(&crtc, this->data, min_t(u32, this->desc->size, sizeof(crtc)));
78
79	switch (request) {
80	case VBIOS_CRTC_ID:
81		*val = crtc.crtc_id;
82		break;
83	case VBIOS_CRTC_ENCODER_ID:
84		*val = crtc.encoder_id;
85		break;
86	case VBIOS_CRTC_MAX_FREQ:
87		*val = crtc.max_freq;
88		break;
89	case VBIOS_CRTC_MAX_WIDTH:
90		*val = crtc.max_width;
91		break;
92	case VBIOS_CRTC_MAX_HEIGHT:
93		*val = crtc.max_height;
94		break;
95	case VBIOS_CRTC_IS_VB_TIMING:
96		*val = crtc.is_vb_timing;
97		break;
98	default:
99		ret = false;
100		break;
101	}
102
103	return ret;
104}
105
106static bool parse_vbios_encoder(struct desc_node *this, struct vbios_cmd *cmd)
107{
108	bool ret = true;
109	u64 request = (u64)cmd->req;
110	u32 *val = (u32 *)cmd->res;
111	struct vbios_encoder encoder;
112
113	memset(&encoder, 0xff, sizeof(encoder));
114	memcpy(&encoder, this->data,
115	       min_t(u32, this->desc->size, sizeof(encoder)));
116
117	switch (request) {
118	case VBIOS_ENCODER_I2C_ID:
119		*val = encoder.i2c_id;
120		break;
121	case VBIOS_ENCODER_CONNECTOR_ID:
122		*val = encoder.connector_id;
123		break;
124	case VBIOS_ENCODER_TYPE:
125		*val = encoder.type;
126		break;
127	case VBIOS_ENCODER_CONFIG_TYPE:
128		*val = encoder.config_type;
129		break;
130	case VBIOS_ENCODER_CHIP:
131		*val = encoder.chip;
132		break;
133	case VBIOS_ENCODER_CHIP_ADDR:
134		*val = encoder.chip_addr;
135		break;
136	default:
137		ret = false;
138		break;
139	}
140
141	return ret;
142}
143
144static bool parse_vbios_cfg_encoder(struct desc_node *this,
145				    struct vbios_cmd *cmd)
146{
147	bool ret = true;
148	u64 request = (u64)cmd->req;
149	u32 *val = (u32 *)cmd->res;
150	struct cfg_encoder *cfg_encoder;
151	struct cfg_encoder *cfg;
152	struct vbios_cfg_encoder *vbios_cfg_encoder;
153	u32 num, size, i = 0;
154
155	vbios_cfg_encoder = (struct vbios_cfg_encoder *)this->data;
156	size = sizeof(struct vbios_cfg_encoder);
157	num = this->desc->size / size;
158
159	switch (request) {
160	case VBIOS_ENCODER_CONFIG_PARAM:
161		cfg_encoder = (struct cfg_encoder *)kzalloc(
162			sizeof(struct cfg_encoder) * num, GFP_KERNEL);
163		cfg = cfg_encoder;
164		for (i = 0; i < num; i++) {
165			cfg->reg_num = vbios_cfg_encoder->reg_num;
166			cfg->hdisplay = vbios_cfg_encoder->hdisplay;
167			cfg->vdisplay = vbios_cfg_encoder->vdisplay;
168			memcpy(&cfg->config_regs,
169			       &vbios_cfg_encoder->config_regs,
170			       sizeof(struct vbios_conf_reg) * 256);
171
172			cfg++;
173			vbios_cfg_encoder++;
174		}
175		cmd->res = (void *)cfg_encoder;
176		break;
177	case VBIOS_ENCODER_CONFIG_NUM:
178		*val = num;
179		break;
180	default:
181		ret = false;
182		break;
183	}
184
185	return ret;
186}
187
188static bool parse_vbios_connector(struct desc_node *this, struct vbios_cmd *cmd)
189{
190	bool ret = true;
191	u64 request = (u64)cmd->req;
192	u32 *val = (u32 *)cmd->res;
193	struct vbios_connector connector;
194
195	memset(&connector, 0xff, sizeof(connector));
196	memcpy(&connector, this->data,
197	       min_t(u32, this->desc->size, sizeof(connector)));
198
199	switch (request) {
200	case VBIOS_CONNECTOR_I2C_ID:
201		*val = connector.i2c_id;
202		break;
203	case VBIOS_CONNECTOR_INTERNAL_EDID:
204		memcpy((u8 *)(ulong)val, connector.internal_edid,
205		       EDID_LENGTH * 2);
206		break;
207	case VBIOS_CONNECTOR_TYPE:
208		*val = connector.type;
209		break;
210	case VBIOS_CONNECTOR_HOTPLUG:
211		*val = connector.hotplug;
212		break;
213	case VBIOS_CONNECTOR_EDID_METHOD:
214		*val = connector.edid_method;
215		break;
216	case VBIOS_CONNECTOR_IRQ_GPIO:
217		*val = connector.irq_gpio;
218		break;
219	case VBIOS_CONNECTOR_IRQ_PLACEMENT:
220		*val = connector.gpio_placement;
221		break;
222	default:
223		ret = false;
224		break;
225	}
226
227	return ret;
228}
229
230static bool parse_vbios_backlight(struct desc_node *this, struct vbios_cmd *cmd)
231{
232	return 0;
233}
234
235static bool parse_vbios_pwm(struct desc_node *this, struct vbios_cmd *cmd)
236{
237	bool ret = true;
238	u64 request = (u64)cmd->req;
239	u32 *val = (u32 *)cmd->res;
240	struct vbios_pwm *pwm = (struct vbios_pwm *)this->data;
241
242	switch (request) {
243	case VBIOS_PWM_ID:
244		*val = pwm->pwm;
245		break;
246	case VBIOS_PWM_PERIOD:
247		*val = pwm->peroid;
248		break;
249	case VBIOS_PWM_POLARITY:
250		*val = pwm->polarity;
251		break;
252	default:
253		ret = false;
254		break;
255	}
256
257	return ret;
258}
259
260static bool parse_vbios_header(struct desc_node *this, struct vbios_cmd *cmd)
261{
262	return true;
263}
264
265static bool parse_vbios_default(struct desc_node *this, struct vbios_cmd *cmd)
266{
267	struct vbios_desc *vb_desc;
268
269	vb_desc = this->desc;
270	DRM_WARN("Current descriptor[T-%d][V-%d] cannot be interprete.\n",
271		 vb_desc->type, vb_desc->ver);
272	return false;
273}
274
275#define FUNC(t, v, f)                                                          \
276	{                                                                      \
277		.type = t, .ver = v, .func = f,                                \
278	}
279
280static struct desc_func tables[] = {
281	FUNC(desc_header, ver_v1, parse_vbios_header),
282	FUNC(desc_i2c, ver_v1, parse_vbios_i2c),
283	FUNC(desc_crtc, ver_v1, parse_vbios_crtc),
284	FUNC(desc_encoder, ver_v1, parse_vbios_encoder),
285	FUNC(desc_connector, ver_v1, parse_vbios_connector),
286	FUNC(desc_cfg_encoder, ver_v1, parse_vbios_cfg_encoder),
287	FUNC(desc_backlight, ver_v1, parse_vbios_backlight),
288	FUNC(desc_pwm, ver_v1, parse_vbios_pwm),
289};
290
291static inline parse_func *get_parse_func(struct vbios_desc *vb_desc)
292{
293	int i;
294	u32 type = vb_desc->type;
295	u32 ver = vb_desc->ver;
296	parse_func *func = parse_vbios_default;
297	u32 tt_num = ARRAY_SIZE(tables);
298
299	for (i = 0; i < tt_num; i++) {
300		if ((tables[i].ver == ver) && (tables[i].type == type)) {
301			func = tables[i].func;
302			break;
303		}
304	}
305
306	return func;
307}
308
309static inline u32 insert_desc_list(struct loongson_drm_device *ldev,
310				   struct vbios_desc *vb_desc)
311{
312	struct desc_node *node;
313	parse_func *func = NULL;
314
315	WARN_ON(!ldev || !vb_desc);
316	node = (struct desc_node *)kzalloc(sizeof(*node), GFP_KERNEL);
317	if (!node)
318		return -ENOMEM;
319
320	func = get_parse_func(vb_desc);
321	node->parse = func;
322	node->desc = (void *)vb_desc;
323	node->data = ((u8 *)ldev->vbios + vb_desc->offset);
324	list_add_tail(&node->head, &ldev->desc_list);
325
326	return 0;
327}
328
329static inline void free_desc_list(struct loongson_drm_device *ldev)
330{
331	struct desc_node *node, *tmp;
332
333	list_for_each_entry_safe (node, tmp, &ldev->desc_list, head) {
334		list_del(&node->head);
335		kfree(node);
336	}
337}
338
339#define DESC_LIST_MAX 1024
340
341static u32 parse_vbios_desc(struct loongson_drm_device *ldev)
342{
343	u32 i, ret = 0;
344	struct vbios_desc *desc;
345	enum desc_type type = 0;
346	u8 *vbios = (u8 *)ldev->vbios;
347
348	WARN_ON(!vbios);
349
350	desc = (struct vbios_desc *)(vbios + VBIOS_DESC_OFFSET);
351	for (i = 0; i < DESC_LIST_MAX; i++) {
352		type = desc->type;
353		if (type == desc_max)
354			break;
355
356		ret = insert_desc_list(ldev, desc);
357		if (ret)
358			DRM_DEBUG_KMS("Parse T-%d V-%d failed[%d]\n", desc->ver,
359				      desc->type, ret);
360
361		desc++;
362	}
363
364	return ret;
365}
366
367static inline struct desc_node *get_desc_node(struct loongson_drm_device *ldev,
368					      u16 type, u8 index)
369{
370	struct desc_node *node, *tmp;
371	struct vbios_desc *vb_desc;
372
373	list_for_each_entry_safe (node, tmp, &ldev->desc_list, head) {
374		vb_desc = node->desc;
375		if (vb_desc->type == type && vb_desc->index == index)
376			return node;
377	}
378
379	return NULL;
380}
381
382static bool vbios_get_data(struct loongson_drm_device *ldev, struct vbios_cmd *cmd)
383{
384	struct desc_node *node;
385
386	WARN_ON(!cmd);
387
388	node = get_desc_node(ldev, cmd->type, cmd->index);
389	if (node && node->parse)
390		return node->parse(node, cmd);
391
392	DRM_DEBUG_DRIVER("Failed to get node(%d,%d)\n", cmd->type, cmd->index);
393
394	return false;
395}
396
397u32 get_connector_type(struct loongson_drm_device *ldev, u32 index)
398{
399	u32 type = -1;
400	bool ret = false;
401	struct vbios_cmd vbt_cmd;
402
403	vbt_cmd.index = index;
404	vbt_cmd.type = desc_connector;
405	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_TYPE;
406	vbt_cmd.res = (void *)(ulong)&type;
407	ret = vbios_get_data(ldev, &vbt_cmd);
408	if (!ret)
409		type = -1;
410
411	return type;
412}
413
414u16 get_connector_i2cid(struct loongson_drm_device *ldev, u32 index)
415{
416	u16 i2c_id = -1;
417	bool ret = false;
418	struct vbios_cmd vbt_cmd;
419
420	vbt_cmd.index = index;
421	vbt_cmd.type = desc_connector;
422	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_I2C_ID;
423	vbt_cmd.res = (void *)(ulong)&i2c_id;
424	ret = vbios_get_data(ldev, &vbt_cmd);
425	if (!ret)
426		i2c_id = -1;
427
428	return i2c_id;
429}
430
431u32 get_connector_irq_gpio(struct loongson_drm_device *ldev, u32 index)
432{
433	int ret;
434	u32 irq_gpio;
435	struct vbios_cmd vbt_cmd;
436
437	vbt_cmd.index = index;
438	vbt_cmd.type = desc_connector;
439	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_IRQ_GPIO;
440	vbt_cmd.res = (void *)(ulong)&irq_gpio;
441	ret = vbios_get_data(ldev, &vbt_cmd);
442	if (!ret)
443		return -1;
444
445	return irq_gpio;
446}
447
448enum gpio_placement get_connector_gpio_placement(struct loongson_drm_device *ldev,
449						 u32 index)
450{
451	int ret;
452	enum gpio_placement irq_placement;
453	struct vbios_cmd vbt_cmd;
454
455	vbt_cmd.index = index;
456	vbt_cmd.type = desc_connector;
457	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_IRQ_PLACEMENT;
458	vbt_cmd.res = (void *)(ulong)&irq_placement;
459	ret = vbios_get_data(ldev, &vbt_cmd);
460	if (!ret)
461		return -1;
462
463	return irq_placement;
464}
465
466u16 get_hotplug_mode(struct loongson_drm_device *ldev, u32 index)
467{
468	u16 mode = -1;
469	bool ret = false;
470	struct vbios_cmd vbt_cmd;
471
472	vbt_cmd.index = index;
473	vbt_cmd.type = desc_connector;
474	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_HOTPLUG;
475	vbt_cmd.res = (void *)(ulong)&mode;
476	ret = vbios_get_data(ldev, &vbt_cmd);
477	if (!ret)
478		mode = -1;
479
480	return mode;
481}
482
483u16 get_edid_method(struct loongson_drm_device *ldev, u32 index)
484{
485	bool ret = false;
486	u16 method = via_null;
487	struct vbios_cmd vbt_cmd;
488
489	vbt_cmd.index = index;
490	vbt_cmd.type = desc_connector;
491	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_EDID_METHOD;
492	vbt_cmd.res = (void *)(ulong)&method;
493	ret = vbios_get_data(ldev, &vbt_cmd);
494	if (!ret)
495		method = via_null;
496
497	return method;
498}
499
500u8 *get_vbios_edid(struct loongson_drm_device *ldev, u32 index)
501{
502	u8 *edid = NULL;
503	bool ret = false;
504	struct vbios_cmd vbt_cmd;
505
506	edid = kzalloc(sizeof(u8) * EDID_LENGTH * 2, GFP_KERNEL);
507	if (!edid)
508		return edid;
509
510	vbt_cmd.index = index;
511	vbt_cmd.type = desc_connector;
512	vbt_cmd.req = (void *)(ulong)VBIOS_CONNECTOR_INTERNAL_EDID;
513	vbt_cmd.res = (void *)(ulong)edid;
514	ret = vbios_get_data(ldev, &vbt_cmd);
515	if (!ret)
516		return NULL;
517
518	return edid;
519}
520
521u32 get_vbios_pwm(struct loongson_drm_device *ldev, u32 index, u16 request)
522{
523	u32 value = -1;
524	bool ret = false;
525	struct vbios_cmd vbt_cmd;
526
527	vbt_cmd.index = index;
528	vbt_cmd.type = desc_pwm;
529	vbt_cmd.req = (void *)(ulong)request;
530	vbt_cmd.res = (void *)(ulong)&value;
531	ret = vbios_get_data(ldev, &vbt_cmd);
532	if (!ret)
533		value = 0xffffffff;
534
535	return value;
536}
537
538u32 get_crtc_id(struct loongson_drm_device *ldev, u32 index)
539{
540	u32 crtc_id = 0;
541	bool ret = false;
542	struct vbios_cmd vbt_cmd;
543
544	vbt_cmd.index = index;
545	vbt_cmd.type = desc_crtc;
546	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_ID;
547	vbt_cmd.res = (void *)(ulong)&crtc_id;
548	ret = vbios_get_data(ldev, &vbt_cmd);
549	if (!ret)
550		crtc_id = 0;
551
552	return crtc_id;
553}
554
555u32 get_crtc_max_freq(struct loongson_drm_device *ldev, u32 index)
556{
557	bool ret = false;
558	u32 max_freq = 0;
559	struct vbios_cmd vbt_cmd;
560
561	vbt_cmd.index = index;
562	vbt_cmd.type = desc_crtc;
563	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_MAX_FREQ;
564	vbt_cmd.res = (void *)(ulong)&max_freq;
565	ret = vbios_get_data(ldev, &vbt_cmd);
566	if (!ret)
567		max_freq = 0;
568
569	return max_freq;
570}
571
572u32 get_crtc_max_width(struct loongson_drm_device *ldev, u32 index)
573{
574	bool ret = false;
575	u32 max_width = 0;
576	struct vbios_cmd vbt_cmd;
577
578	vbt_cmd.index = index;
579	vbt_cmd.type = desc_crtc;
580	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_MAX_WIDTH;
581	vbt_cmd.res = (void *)(ulong)&max_width;
582	ret = vbios_get_data(ldev, &vbt_cmd);
583	if (!ret)
584		max_width = LOONGSON_MAX_FB_WIDTH;
585
586	return max_width;
587}
588
589u32 get_crtc_max_height(struct loongson_drm_device *ldev, u32 index)
590{
591	bool ret = false;
592	u32 max_height = 0;
593	struct vbios_cmd vbt_cmd;
594
595	vbt_cmd.index = index;
596	vbt_cmd.type = desc_crtc;
597	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_MAX_HEIGHT;
598	vbt_cmd.res = (void *)(ulong)&max_height;
599	ret = vbios_get_data(ldev, &vbt_cmd);
600	if (!ret)
601		max_height = LOONGSON_MAX_FB_HEIGHT;
602
603	return max_height;
604}
605
606u32 get_crtc_encoder_id(struct loongson_drm_device *ldev, u32 index)
607{
608	bool ret = false;
609	u32 encoder_id = 0;
610	struct vbios_cmd vbt_cmd;
611
612	vbt_cmd.index = index;
613	vbt_cmd.type = desc_crtc;
614	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_ENCODER_ID;
615	vbt_cmd.res = (void *)(ulong)&encoder_id;
616	ret = vbios_get_data(ldev, &vbt_cmd);
617	if (!ret)
618		encoder_id = 0;
619
620	return encoder_id;
621}
622
623bool get_crtc_is_vb_timing(struct loongson_drm_device *ldev, u32 index)
624{
625	bool ret = false;
626	bool vb_timing = false;
627	struct vbios_cmd vbt_cmd;
628
629	vbt_cmd.index = index;
630	vbt_cmd.type = desc_crtc;
631	vbt_cmd.req = (void *)(ulong)VBIOS_CRTC_IS_VB_TIMING;
632	vbt_cmd.res = (void *)(ulong)&vb_timing;
633	ret = vbios_get_data(ldev, &vbt_cmd);
634	if (!ret)
635		vb_timing = false;
636
637	return vb_timing;
638}
639
640struct crtc_timing *get_crtc_timing(struct loongson_drm_device *ldev, u32 index)
641{
642	return NULL;
643}
644
645u32 get_encoder_connector_id(struct loongson_drm_device *ldev, u32 index)
646{
647	bool ret = false;
648	u32 connector_id = 0;
649	struct vbios_cmd vbt_cmd;
650
651	vbt_cmd.index = index;
652	vbt_cmd.type = desc_encoder;
653	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CONNECTOR_ID;
654	vbt_cmd.res = (void *)(ulong)&connector_id;
655	ret = vbios_get_data(ldev, &vbt_cmd);
656	if (!ret)
657		connector_id = 0;
658
659	return connector_id;
660}
661
662u32 get_encoder_i2c_id(struct loongson_drm_device *ldev, u32 index)
663{
664	u32 i2c_id = 0;
665	bool ret = false;
666	struct vbios_cmd vbt_cmd;
667
668	vbt_cmd.index = index;
669	vbt_cmd.type = desc_encoder;
670	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_I2C_ID;
671	vbt_cmd.res = (void *)(ulong)&i2c_id;
672	ret = vbios_get_data(ldev, &vbt_cmd);
673	if (!ret)
674		i2c_id = 0;
675
676	return i2c_id;
677}
678
679struct cfg_encoder *get_encoder_config(struct loongson_drm_device *ldev, u32 index)
680{
681	bool ret = false;
682	struct vbios_cmd vbt_cmd;
683	struct cfg_encoder *encoder_config = NULL;
684
685	vbt_cmd.index = index;
686	vbt_cmd.type = desc_cfg_encoder;
687	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CONFIG_PARAM;
688	ret = vbios_get_data(ldev, &vbt_cmd);
689	if (ret)
690		encoder_config = (struct cfg_encoder *)vbt_cmd.res;
691
692	return encoder_config;
693}
694
695u32 get_encoder_cfg_num(struct loongson_drm_device *ldev, u32 index)
696{
697	struct vbios_cmd vbt_cmd;
698	bool ret = false;
699	u32 cfg_num = 0;
700
701	vbt_cmd.index = index;
702	vbt_cmd.type = desc_cfg_encoder;
703	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CONFIG_NUM;
704	vbt_cmd.res = (void *)(ulong)&cfg_num;
705	ret = vbios_get_data(ldev, &vbt_cmd);
706	if (!ret)
707		cfg_num = 0;
708
709	return cfg_num;
710}
711
712enum encoder_config get_encoder_config_type(struct loongson_drm_device *ldev,
713					    u32 index)
714{
715	bool ret = false;
716	enum encoder_config config_type = encoder_bios_config;
717	struct vbios_cmd vbt_cmd;
718
719	vbt_cmd.index = index;
720	vbt_cmd.type = desc_encoder;
721	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CONFIG_TYPE;
722	vbt_cmd.res = (void *)(ulong)&config_type;
723	ret = vbios_get_data(ldev, &vbt_cmd);
724	if (!ret)
725		config_type = encoder_bios_config;
726
727	return config_type;
728}
729
730enum encoder_object get_encoder_chip(struct loongson_drm_device *ldev, u32 index)
731{
732	int ret;
733	enum encoder_object chip;
734	struct vbios_cmd vbt_cmd;
735
736	vbt_cmd.index = index;
737	vbt_cmd.type = desc_encoder;
738	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CHIP;
739	vbt_cmd.res = (void *)(ulong)&chip;
740	ret = vbios_get_data(ldev, &vbt_cmd);
741	if (!ret)
742		return Unknown;
743
744	return chip;
745}
746
747u8 get_encoder_chip_addr(struct loongson_drm_device *ldev, u32 index)
748{
749	int ret;
750	u8 chip_addr;
751	struct vbios_cmd vbt_cmd;
752
753	vbt_cmd.index = index;
754	vbt_cmd.type = desc_encoder;
755	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_CHIP_ADDR;
756	vbt_cmd.res = (void *)(ulong)&chip_addr;
757	ret = vbios_get_data(ldev, &vbt_cmd);
758	if (!ret)
759		return Unknown;
760
761	return chip_addr;
762}
763
764enum encoder_type get_encoder_type(struct loongson_drm_device *ldev, u32 index)
765{
766	bool ret = false;
767	enum encoder_type type = encoder_dac;
768	struct vbios_cmd vbt_cmd;
769
770	vbt_cmd.index = index;
771	vbt_cmd.type = desc_encoder;
772	vbt_cmd.req = (void *)(ulong)VBIOS_ENCODER_TYPE;
773	vbt_cmd.res = (void *)(ulong)&type;
774	ret = vbios_get_data(ldev, &vbt_cmd);
775	if (!ret)
776		type = encoder_dac;
777
778	return type;
779}
780
781bool get_loongson_i2c(struct loongson_drm_device *ldev)
782{
783	bool ret = false;
784	struct vbios_cmd vbt_cmd;
785
786	vbt_cmd.index = 0;
787	vbt_cmd.type = desc_i2c;
788	vbt_cmd.res = (void *)&ldev->i2c_bus;
789	ret = vbios_get_data(ldev, &vbt_cmd);
790
791	if (!ret) {
792		ldev->i2c_bus[0].use = true;
793		ldev->i2c_bus[1].use = true;
794	}
795
796	return true;
797}
798
799static void *get_vbios_from_acpi(struct loongson_drm_device *ldev)
800{
801	void *vbios = NULL;
802#ifdef CONFIG_ACPI
803	struct acpi_viat_table *viat;
804	struct acpi_table_header *hdr;
805
806	if (!ACPI_SUCCESS(acpi_get_table("VIAT", 1, &hdr)))
807		return NULL;
808
809	if (hdr->length != sizeof(struct acpi_viat_table)) {
810		DRM_WARN("ACPI VIAT table present but broken (length error)\n");
811		return NULL;
812	}
813
814	vbios = kmalloc(VBIOS_SIZE, GFP_KERNEL);
815	if (!vbios)
816		return NULL;
817
818	viat = (struct acpi_viat_table *)hdr;
819	memcpy(vbios, phys_to_virt(viat->vbios_addr), VBIOS_SIZE);
820
821	DRM_INFO("Get VBIOS from ACPI success!\n");
822#endif
823	return vbios;
824}
825
826static void *get_vbios_from_vram(struct loongson_drm_device *ldev)
827{
828	void *bios, *vbios = NULL;
829	u64 vram_base = pci_resource_start(ldev->gpu_pdev, 2);
830	u64 vram_size = pci_resource_len(ldev->gpu_pdev, 2);
831	u64 vbios_addr = vram_base + vram_size - VBIOS_OFFSET;
832
833	bios = ioremap(vbios_addr, VBIOS_SIZE);
834	if (!bios)
835		return NULL;
836
837	vbios = kmalloc(VBIOS_SIZE, GFP_KERNEL);
838	if (!vbios)
839		return NULL;
840
841	memcpy(vbios, bios, VBIOS_SIZE);
842
843	iounmap(bios);
844
845	if (memcmp(vbios, VBIOS_TITLE, strlen(VBIOS_TITLE))) {
846		kfree(vbios);
847		return NULL;
848	}
849
850	DRM_INFO("Get VBIOS from VRAM success!\n");
851
852	return vbios;
853}
854
855bool loongson_vbios_init(struct loongson_drm_device *ldev)
856{
857	void *vbios = NULL;
858	struct loongson_vbios *header;
859
860	vbios = get_vbios_from_vram(ldev);
861	if (vbios)
862		goto success;
863
864	vbios = get_vbios_from_acpi(ldev);
865	if (vbios)
866		goto success;
867
868	vbios = kzalloc(256 * 1024, GFP_KERNEL);
869	if (!vbios)
870		return false;
871
872	header = vbios;
873	header->crtc_num = 2;
874
875success:
876	header = ldev->vbios = vbios;
877	ldev->num_crtc = header->crtc_num;
878
879	DRM_INFO("Loongson VBIOS version %d.%d\n", header->version_major,
880		 header->version_minor);
881
882	INIT_LIST_HEAD(&ldev->desc_list);
883	parse_vbios_desc(ldev);
884
885	return true;
886}
887
888void loongson_vbios_exit(struct loongson_drm_device *ldev)
889{
890	free_desc_list(ldev);
891	kfree(ldev->vbios);
892}
893