25 #include <linux/module.h>
26 #include <linux/sched.h>
27 #include <linux/slab.h>
28 #include <asm/unaligned.h>
37 #define ATOM_COND_ABOVE 0
38 #define ATOM_COND_ABOVEOREQUAL 1
39 #define ATOM_COND_ALWAYS 2
40 #define ATOM_COND_BELOW 3
41 #define ATOM_COND_BELOWOREQUAL 4
42 #define ATOM_COND_EQUAL 5
43 #define ATOM_COND_NOTEQUAL 6
45 #define ATOM_PORT_ATI 0
46 #define ATOM_PORT_PCI 1
47 #define ATOM_PORT_SYSIO 2
49 #define ATOM_UNIT_MICROSEC 0
50 #define ATOM_UNIT_MILLISEC 1
70 { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000,
72 static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 };
74 static int atom_dst_to_src[8][4] = {
85 static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 };
87 static int debug_depth = 0;
89 static void debug_print_spaces(
int n)
95 #define DEBUG(...) do if (atom_debug) { printk(KERN_DEBUG __VA_ARGS__); } while (0)
96 #define SDEBUG(...) do if (atom_debug) { printk(KERN_DEBUG); debug_print_spaces(debug_depth); printk(__VA_ARGS__); } while (0)
98 #define DEBUG(...) do { } while (0)
99 #define SDEBUG(...) do { } while (0)
114 temp = ctx->
card->ioreg_read(ctx->
card,
CU16(base + 1));
120 ctx->
card->ioreg_write(ctx->
card,
CU16(base + 1), temp);
125 ~((0xFFFFFFFF >> (32 -
CU8(base + 1))) <<
131 (0xFFFFFFFF >> (32 -
CU8(base + 1))) <<
CU8(base +
137 ~((0xFFFFFFFF >> (32 -
CU8(base + 1))) <<
140 ((index >>
CU8(base + 2)) &
141 (0xFFFFFFFF >> (32 -
CU8(base + 1)))) <<
CU8(base +
147 ~((0xFFFFFFFF >> (32 -
CU8(base + 1))) <<
150 ((data >>
CU8(base + 2)) &
151 (0xFFFFFFFF >> (32 -
CU8(base + 1)))) <<
CU8(base +
157 ~((0xFFFFFFFF >> (32 -
CU8(base + 1))) <<
161 io_attr >>
CU8(base + 2)) & (0xFFFFFFFF >> (32 -
183 align = (attr >> 3) & 7;
189 DEBUG(
"REG[0x%04X]", idx);
193 val = gctx->
card->reg_read(gctx->
card, idx);
197 "PCI registers are not implemented.\n");
201 "SYSIO registers are not implemented.\n");
210 "Undefined indirect IO read method %d.\n",
215 atom_iio_execute(gctx,
227 DEBUG(
"PS[0x%02X,0x%04X]", idx, val);
233 DEBUG(
"WS[0x%02X]", idx);
248 val = 1 << gctx->
shift;
251 val = ~(1 << gctx->
shift);
273 DEBUG(
"ID[0x%04X]", idx);
281 DRM_ERROR(
"ATOM: fb read beyond scratch region: %d vs. %d\n",
287 DEBUG(
"FB[0x%02X]", idx);
295 DEBUG(
"IMM 0x%08X\n", val);
303 DEBUG(
"IMM 0x%04X\n", val);
312 DEBUG(
"IMM 0x%02X\n", val);
320 DEBUG(
"PLL[0x%02X]", idx);
321 val = gctx->
card->pll_read(gctx->
card, idx);
327 DEBUG(
"MC[0x%02X]", idx);
328 val = gctx->
card->mc_read(gctx->
card, idx);
333 val &= atom_arg_mask[
align];
334 val >>= atom_arg_shift[
align];
338 DEBUG(
".[31:0] -> 0x%08X\n", val);
341 DEBUG(
".[15:0] -> 0x%04X\n", val);
344 DEBUG(
".[23:8] -> 0x%04X\n", val);
347 DEBUG(
".[31:16] -> 0x%04X\n", val);
350 DEBUG(
".[7:0] -> 0x%02X\n", val);
353 DEBUG(
".[15:8] -> 0x%02X\n", val);
356 DEBUG(
".[23:16] -> 0x%02X\n", val);
359 DEBUG(
".[31:24] -> 0x%02X\n", val);
403 return atom_get_src_int(ctx, attr, ptr,
NULL, 1);
433 int *ptr,
uint32_t *saved,
int print)
435 return atom_get_src_int(ctx,
436 arg | atom_dst_to_src[(attr >> 3) &
437 7][(attr >> 6) & 3] << 3,
443 atom_skip_src_int(ctx,
444 arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) &
452 atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val =
455 old_val &= atom_arg_mask[
align] >> atom_arg_shift[
align];
456 val <<= atom_arg_shift[
align];
457 val &= atom_arg_mask[
align];
458 saved &= ~atom_arg_mask[
align];
464 DEBUG(
"REG[0x%04X]", idx);
469 gctx->
card->reg_write(gctx->
card, idx,
472 gctx->
card->reg_write(gctx->
card, idx, val);
476 "PCI registers are not implemented.\n");
480 "SYSIO registers are not implemented.\n");
489 "Undefined indirect IO write method %d.\n",
493 atom_iio_execute(gctx, gctx->
iio[gctx->
io_mode & 0xFF],
500 DEBUG(
"PS[0x%02X]", idx);
506 DEBUG(
"WS[0x%02X]", idx);
540 DRM_ERROR(
"ATOM: fb write beyond scratch region: %d vs. %d\n",
544 DEBUG(
"FB[0x%02X]", idx);
549 DEBUG(
"PLL[0x%02X]", idx);
550 gctx->
card->pll_write(gctx->
card, idx, val);
555 DEBUG(
"MC[0x%02X]", idx);
556 gctx->
card->mc_write(gctx->
card, idx, val);
561 DEBUG(
".[31:0] <- 0x%08X\n", old_val);
564 DEBUG(
".[15:0] <- 0x%04X\n", old_val);
567 DEBUG(
".[23:8] <- 0x%04X\n", old_val);
570 DEBUG(
".[31:16] <- 0x%04X\n", old_val);
573 DEBUG(
".[7:0] <- 0x%02X\n", old_val);
576 DEBUG(
".[15:8] <- 0x%02X\n", old_val);
579 DEBUG(
".[23:16] <- 0x%02X\n", old_val);
582 DEBUG(
".[31:24] <- 0x%02X\n", old_val);
593 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
595 src = atom_get_src(ctx, attr, ptr);
598 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
607 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
609 src = atom_get_src(ctx, attr, ptr);
612 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
617 printk(
"ATOM BIOS beeped!\n");
622 int idx =
U8((*ptr)++);
626 SDEBUG(
" table: %d (%s)\n", idx, atom_table_names[idx]);
628 SDEBUG(
" table: %d\n", idx);
629 if (
U16(ctx->
ctx->cmd_table + 4 + 2 * idx))
630 r = atom_execute_table_locked(ctx->
ctx, idx, ctx->
ps + ctx->
ps_shift);
642 attr |= atom_def_dst[attr >> 3] << 6;
643 atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
645 atom_put_dst(ctx, arg, attr, &dptr, 0, saved);
653 dst = atom_get_dst(ctx, arg, attr, ptr,
NULL, 1);
655 src = atom_get_src(ctx, attr, ptr);
656 ctx->
ctx->cs_equal = (dst ==
src);
657 ctx->
ctx->cs_above = (dst >
src);
658 SDEBUG(
" result: %s %s\n", ctx->
ctx->cs_equal ?
"EQ" :
"NE",
659 ctx->
ctx->cs_above ?
"GT" :
"LE");
665 SDEBUG(
" count: %d\n", count);
668 else if (!drm_can_sleep())
679 dst = atom_get_dst(ctx, arg, attr, ptr,
NULL, 1);
681 src = atom_get_src(ctx, attr, ptr);
683 ctx->
ctx->divmul[0] = dst /
src;
684 ctx->
ctx->divmul[1] = dst %
src;
686 ctx->
ctx->divmul[0] = 0;
687 ctx->
ctx->divmul[1] = 0;
699 unsigned long cjiffies;
704 execute = ctx->
ctx->cs_above;
707 execute = ctx->
ctx->cs_above || ctx->
ctx->cs_equal;
713 execute = !(ctx->
ctx->cs_above || ctx->
ctx->cs_equal);
716 execute = !ctx->
ctx->cs_above;
719 execute = ctx->
ctx->cs_equal;
722 execute = !ctx->
ctx->cs_equal;
726 SDEBUG(
" taken: %s\n", execute ?
"yes" :
"no");
734 DRM_ERROR(
"atombios stuck in loop for more than 5secs aborting\n");
755 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
756 mask = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
757 SDEBUG(
" mask: 0x%08x", mask);
759 src = atom_get_src(ctx, attr, ptr);
763 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
772 atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
774 atom_skip_dst(ctx, arg, attr, ptr);
778 src = atom_get_src(ctx, attr, ptr);
780 atom_put_dst(ctx, arg, attr, &dptr, src, saved);
788 dst = atom_get_dst(ctx, arg, attr, ptr,
NULL, 1);
790 src = atom_get_src(ctx, attr, ptr);
791 ctx->
ctx->divmul[0] = dst *
src;
805 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
807 src = atom_get_src(ctx, attr, ptr);
810 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
816 SDEBUG(
"POST card output: 0x%02X\n", val);
838 SDEBUG(
" block: %d\n", idx);
840 ctx->
ctx->data_block = 0;
844 ctx->
ctx->data_block =
U16(ctx->
ctx->data_table + 4 + 2 * idx);
845 SDEBUG(
" base: 0x%04X\n", ctx->
ctx->data_block);
852 ctx->
ctx->fb_base = atom_get_src(ctx, attr, ptr);
862 SDEBUG(
" port: %d (%s)\n", port, atom_io_names[port]);
864 SDEBUG(
" port: %d\n", port);
884 ctx->
ctx->reg_block =
U16(*ptr);
886 SDEBUG(
" base: 0x%04X\n", ctx->
ctx->reg_block);
895 attr |= atom_def_dst[attr >> 3] << 6;
897 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
902 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
911 attr |= atom_def_dst[attr >> 3] << 6;
913 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
918 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
926 uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
928 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
931 shift = atom_get_src(ctx, attr, ptr);
934 dst &= atom_arg_mask[dst_align];
935 dst >>= atom_arg_shift[dst_align];
937 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
945 uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
947 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
950 shift = atom_get_src(ctx, attr, ptr);
953 dst &= atom_arg_mask[dst_align];
954 dst >>= atom_arg_shift[dst_align];
956 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
965 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
967 src = atom_get_src(ctx, attr, ptr);
970 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
978 src = atom_get_src(ctx, attr, ptr);
988 SDEBUG(
" target: %04X\n", target);
1005 dst = atom_get_dst(ctx, arg, attr, ptr,
NULL, 1);
1007 src = atom_get_src(ctx, attr, ptr);
1008 ctx->
ctx->cs_equal = ((dst &
src) == 0);
1009 SDEBUG(
" result: %s\n", ctx->
ctx->cs_equal ?
"EQ" :
"NE");
1018 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
1020 src = atom_get_src(ctx, attr, ptr);
1023 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
1094 atom_op_setregblock, 0}, {
1095 atom_op_setfbbase, 0}, {
1102 atom_op_switch, 0}, {
1118 atom_op_calltable, 0}, {
1119 atom_op_repeat, 0}, {
1134 atom_op_postcard, 0}, {
1136 atom_op_savereg, 0}, {
1137 atom_op_restorereg, 0}, {
1138 atom_op_setdatablock, 0}, {
1157 atom_op_debug, 0},};
1175 SDEBUG(
">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
1192 SDEBUG(
"%s @ 0x%04X\n", atom_op_names[op], ptr - 1);
1194 SDEBUG(
"[%d] @ 0x%04X\n", op, ptr - 1);
1196 DRM_ERROR(
"atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",
1197 base, len, ws, ps, ptr - 1);
1203 opcode_table[
op].func(&ectx, &ptr,
1204 opcode_table[op].arg);
1231 r = atom_execute_table_locked(ctx, index, params);
1236 static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
1238 static void atom_index_iio(
struct atom_context *ctx,
int base)
1242 ctx->
iio[
CU8(base + 1)] = base + 2;
1245 base += atom_iio_len[
CU8(base)];
1292 while (*str && ((*str ==
'\n') || (*str ==
'\r')))
1295 for (i = 0; i < 511; i++) {
1297 if (name[i] <
'.' || name[i] >
'z') {
1318 if (!ps[0] || !ps[1])
1347 int offset = index * 2 + 4;
1357 *frev =
CU8(idx + 2);
1359 *crev =
CU8(idx + 3);
1367 int offset = index * 2 + 4;
1375 *frev =
CU8(idx + 2);
1377 *crev =
CU8(idx + 3);
1385 int usage_bytes = 0;
1391 DRM_DEBUG(
"atom firmware requested %08x %dkb\n",
1398 if (usage_bytes == 0)
1399 usage_bytes = 20 * 1024;