^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2008 Advanced Micro Devices, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Permission is hereby granted, free of charge, to any person obtaining a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * copy of this software and associated documentation files (the "Software"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * to deal in the Software without restriction, including without limitation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * and/or sell copies of the Software, and to permit persons to whom the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Software is furnished to do so, subject to the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * The above copyright notice and this permission notice shall be included in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * all copies or substantial portions of the Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * OTHER DEALINGS IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Author: Stanislaw Skowronek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <drm/drm_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <drm/drm_util.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ATOM_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "atom.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include "atom-names.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "atom-bits.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "radeon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ATOM_COND_ABOVE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ATOM_COND_ABOVEOREQUAL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define ATOM_COND_ALWAYS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define ATOM_COND_BELOW 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define ATOM_COND_BELOWOREQUAL 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define ATOM_COND_EQUAL 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define ATOM_COND_NOTEQUAL 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define ATOM_PORT_ATI 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ATOM_PORT_PCI 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ATOM_PORT_SYSIO 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define ATOM_UNIT_MICROSEC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ATOM_UNIT_MILLISEC 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PLL_INDEX 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PLL_DATA 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct atom_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) uint32_t *ps, *ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ps_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) uint16_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned last_jump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long last_jump_jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bool abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) } atom_exec_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int atom_debug = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static uint32_t atom_arg_mask[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 0xFFFFFFFF, 0x0000FFFF, 0x00FFFF00, 0xFFFF0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int atom_dst_to_src[8][4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* translate destination alignment field to the source alignment encoding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {0, 0, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {1, 2, 3, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {1, 2, 3, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {1, 2, 3, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {4, 5, 6, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {4, 5, 6, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {4, 5, 6, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {4, 5, 6, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int debug_depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #ifdef ATOM_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static void debug_print_spaces(int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) while (n--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) printk(" ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define DEBUG(...) do if (atom_debug) { printk(KERN_DEBUG __VA_ARGS__); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define SDEBUG(...) do if (atom_debug) { printk(KERN_DEBUG); debug_print_spaces(debug_depth); printk(__VA_ARGS__); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DEBUG(...) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define SDEBUG(...) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) uint32_t index, uint32_t data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct radeon_device *rdev = ctx->card->dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) uint32_t temp = 0xCDCDCDCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) switch (CU8(base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case ATOM_IIO_NOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) base++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case ATOM_IIO_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) temp = ctx->card->ioreg_read(ctx->card, CU16(base + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) base += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case ATOM_IIO_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (rdev->family == CHIP_RV515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) (void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) base += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case ATOM_IIO_CLEAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) temp &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) CU8(base + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) base += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case ATOM_IIO_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) temp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) (0xFFFFFFFF >> (32 - CU8(base + 1))) << CU8(base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) base += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case ATOM_IIO_MOVE_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) temp &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) CU8(base + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) temp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ((index >> CU8(base + 2)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) base += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case ATOM_IIO_MOVE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) temp &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) CU8(base + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) temp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ((data >> CU8(base + 2)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) base += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case ATOM_IIO_MOVE_ATTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) temp &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) CU8(base + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) temp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ((ctx->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) CU8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) (base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 1))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) << CU8(base + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) base += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case ATOM_IIO_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pr_info("Unknown IIO opcode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int *ptr, uint32_t *saved, int print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) uint32_t idx, val = 0xCDCDCDCD, align, arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct atom_context *gctx = ctx->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) arg = attr & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) align = (attr >> 3) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case ATOM_ARG_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) idx = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) DEBUG("REG[0x%04X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) idx += gctx->reg_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) switch (gctx->io_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case ATOM_IO_MM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) val = gctx->card->reg_read(gctx->card, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case ATOM_IO_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pr_info("PCI registers are not implemented\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case ATOM_IO_SYSIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pr_info("SYSIO registers are not implemented\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!(gctx->io_mode & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pr_info("Bad IO mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!gctx->iio[gctx->io_mode & 0x7F]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) pr_info("Undefined indirect IO read method %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) gctx->io_mode & 0x7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) atom_iio_execute(gctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) gctx->iio[gctx->io_mode & 0x7F],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) idx, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case ATOM_ARG_PS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* get_unaligned_le32 avoids unaligned accesses from atombios
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * tables, noticed on a DEC Alpha. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val = get_unaligned_le32((u32 *)&ctx->ps[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) DEBUG("PS[0x%02X,0x%04X]", idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case ATOM_ARG_WS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) DEBUG("WS[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) switch (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case ATOM_WS_QUOTIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) val = gctx->divmul[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case ATOM_WS_REMAINDER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) val = gctx->divmul[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case ATOM_WS_DATAPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) val = gctx->data_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case ATOM_WS_SHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) val = gctx->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case ATOM_WS_OR_MASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) val = 1 << gctx->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case ATOM_WS_AND_MASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) val = ~(1 << gctx->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case ATOM_WS_FB_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) val = gctx->fb_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case ATOM_WS_ATTRIBUTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) val = gctx->io_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case ATOM_WS_REGPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) val = gctx->reg_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) val = ctx->ws[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case ATOM_ARG_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) idx = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (print) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (gctx->data_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) DEBUG("ID[0x%04X+%04X]", idx, gctx->data_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) DEBUG("ID[0x%04X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) val = U32(idx + gctx->data_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case ATOM_ARG_FB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) DRM_ERROR("ATOM: fb read beyond scratch region: %d vs. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) val = gctx->scratch[(gctx->fb_base / 4) + idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) DEBUG("FB[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case ATOM_ARG_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) switch (align) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) case ATOM_SRC_DWORD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) val = U32(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) (*ptr) += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) DEBUG("IMM 0x%08X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case ATOM_SRC_WORD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case ATOM_SRC_WORD8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case ATOM_SRC_WORD16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) val = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) DEBUG("IMM 0x%04X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case ATOM_SRC_BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case ATOM_SRC_BYTE8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case ATOM_SRC_BYTE16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case ATOM_SRC_BYTE24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) DEBUG("IMM 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case ATOM_ARG_PLL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) DEBUG("PLL[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val = gctx->card->pll_read(gctx->card, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case ATOM_ARG_MC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) DEBUG("MC[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) val = gctx->card->mc_read(gctx->card, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (saved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *saved = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) val &= atom_arg_mask[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) val >>= atom_arg_shift[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) switch (align) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case ATOM_SRC_DWORD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) DEBUG(".[31:0] -> 0x%08X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case ATOM_SRC_WORD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) DEBUG(".[15:0] -> 0x%04X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case ATOM_SRC_WORD8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) DEBUG(".[23:8] -> 0x%04X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case ATOM_SRC_WORD16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) DEBUG(".[31:16] -> 0x%04X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case ATOM_SRC_BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) DEBUG(".[7:0] -> 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case ATOM_SRC_BYTE8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) DEBUG(".[15:8] -> 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case ATOM_SRC_BYTE16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) DEBUG(".[23:16] -> 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case ATOM_SRC_BYTE24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) DEBUG(".[31:24] -> 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) uint32_t align = (attr >> 3) & 7, arg = attr & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case ATOM_ARG_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case ATOM_ARG_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case ATOM_ARG_PLL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case ATOM_ARG_MC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) case ATOM_ARG_PS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case ATOM_ARG_WS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case ATOM_ARG_FB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case ATOM_ARG_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) switch (align) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case ATOM_SRC_DWORD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) (*ptr) += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case ATOM_SRC_WORD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case ATOM_SRC_WORD8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case ATOM_SRC_WORD16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case ATOM_SRC_BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case ATOM_SRC_BYTE8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case ATOM_SRC_BYTE16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case ATOM_SRC_BYTE24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return atom_get_src_int(ctx, attr, ptr, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) uint32_t val = 0xCDCDCDCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) switch (align) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case ATOM_SRC_DWORD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) val = U32(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) (*ptr) += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case ATOM_SRC_WORD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) case ATOM_SRC_WORD8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) case ATOM_SRC_WORD16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) val = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case ATOM_SRC_BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case ATOM_SRC_BYTE8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case ATOM_SRC_BYTE16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) case ATOM_SRC_BYTE24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) val = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int *ptr, uint32_t *saved, int print)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return atom_get_src_int(ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) arg | atom_dst_to_src[(attr >> 3) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 7][(attr >> 6) & 3] << 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ptr, saved, print);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static void atom_skip_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) atom_skip_src_int(ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 3] << 3, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int *ptr, uint32_t val, uint32_t saved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) uint32_t align =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) val, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct atom_context *gctx = ctx->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) old_val &= atom_arg_mask[align] >> atom_arg_shift[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) val <<= atom_arg_shift[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) val &= atom_arg_mask[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) saved &= ~atom_arg_mask[align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) val |= saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case ATOM_ARG_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) idx = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) DEBUG("REG[0x%04X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) idx += gctx->reg_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) switch (gctx->io_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case ATOM_IO_MM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (idx == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) gctx->card->reg_write(gctx->card, idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) val << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) gctx->card->reg_write(gctx->card, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) case ATOM_IO_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pr_info("PCI registers are not implemented\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case ATOM_IO_SYSIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pr_info("SYSIO registers are not implemented\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!(gctx->io_mode & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) pr_info("Bad IO mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!gctx->iio[gctx->io_mode & 0xFF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) pr_info("Undefined indirect IO write method %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) gctx->io_mode & 0x7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) atom_iio_execute(gctx, gctx->iio[gctx->io_mode & 0xFF],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case ATOM_ARG_PS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) DEBUG("PS[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ctx->ps[idx] = cpu_to_le32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case ATOM_ARG_WS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) DEBUG("WS[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) switch (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case ATOM_WS_QUOTIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) gctx->divmul[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case ATOM_WS_REMAINDER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) gctx->divmul[1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case ATOM_WS_DATAPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) gctx->data_block = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case ATOM_WS_SHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) gctx->shift = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case ATOM_WS_OR_MASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case ATOM_WS_AND_MASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case ATOM_WS_FB_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) gctx->fb_base = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case ATOM_WS_ATTRIBUTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) gctx->io_attr = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case ATOM_WS_REGPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) gctx->reg_block = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ctx->ws[idx] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case ATOM_ARG_FB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) DRM_ERROR("ATOM: fb write beyond scratch region: %d vs. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) gctx->scratch[(gctx->fb_base / 4) + idx] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) DEBUG("FB[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case ATOM_ARG_PLL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) DEBUG("PLL[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) gctx->card->pll_write(gctx->card, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case ATOM_ARG_MC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) DEBUG("MC[0x%02X]", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) gctx->card->mc_write(gctx->card, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) switch (align) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) case ATOM_SRC_DWORD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) DEBUG(".[31:0] <- 0x%08X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case ATOM_SRC_WORD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) DEBUG(".[15:0] <- 0x%04X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case ATOM_SRC_WORD8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) DEBUG(".[23:8] <- 0x%04X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case ATOM_SRC_WORD16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) DEBUG(".[31:16] <- 0x%04X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case ATOM_SRC_BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) DEBUG(".[7:0] <- 0x%02X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case ATOM_SRC_BYTE8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) DEBUG(".[15:8] <- 0x%02X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) case ATOM_SRC_BYTE16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) DEBUG(".[23:16] <- 0x%02X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case ATOM_SRC_BYTE24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) DEBUG(".[31:24] <- 0x%02X\n", old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static void atom_op_add(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) uint32_t dst, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) dst += src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static void atom_op_and(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) uint32_t dst, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) dst &= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) printk("ATOM BIOS beeped!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int idx = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (idx < ATOM_TABLE_NAMES_CNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) SDEBUG(" table: %d\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ctx->abort = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) uint32_t saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) attr &= 0x38;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) attr |= atom_def_dst[attr >> 3] << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) atom_put_dst(ctx, arg, attr, &dptr, 0, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) uint32_t dst, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) SDEBUG(" src1: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) SDEBUG(" src2: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ctx->ctx->cs_equal = (dst == src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ctx->ctx->cs_above = (dst > src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) SDEBUG(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ" : "NE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ctx->ctx->cs_above ? "GT" : "LE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) unsigned count = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) SDEBUG(" count: %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (arg == ATOM_UNIT_MICROSEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) udelay(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) else if (!drm_can_sleep())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) mdelay(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) msleep(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) uint32_t dst, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) SDEBUG(" src1: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) SDEBUG(" src2: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (src != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ctx->ctx->divmul[0] = dst / src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ctx->ctx->divmul[1] = dst % src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ctx->ctx->divmul[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ctx->ctx->divmul[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* functionally, a nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int execute = 0, target = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) unsigned long cjiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case ATOM_COND_ABOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) execute = ctx->ctx->cs_above;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case ATOM_COND_ABOVEOREQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) execute = ctx->ctx->cs_above || ctx->ctx->cs_equal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case ATOM_COND_ALWAYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) execute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) case ATOM_COND_BELOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) execute = !(ctx->ctx->cs_above || ctx->ctx->cs_equal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) case ATOM_COND_BELOWOREQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) execute = !ctx->ctx->cs_above;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) case ATOM_COND_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) execute = ctx->ctx->cs_equal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case ATOM_COND_NOTEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) execute = !ctx->ctx->cs_equal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (arg != ATOM_COND_ALWAYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) SDEBUG(" taken: %s\n", execute ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) SDEBUG(" target: 0x%04X\n", target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (execute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (ctx->last_jump == (ctx->start + target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) cjiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (time_after(cjiffies, ctx->last_jump_jiffies)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) cjiffies -= ctx->last_jump_jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if ((jiffies_to_msecs(cjiffies) > 5000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) DRM_ERROR("atombios stuck in loop for more than 5secs aborting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ctx->abort = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /* jiffies wrap around we will just wait a little longer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ctx->last_jump_jiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) ctx->last_jump = ctx->start + target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ctx->last_jump_jiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) *ptr = ctx->start + target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) uint32_t dst, mask, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) mask = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) SDEBUG(" mask: 0x%08x", mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dst &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dst |= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static void atom_op_move(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) uint32_t src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (((attr >> 3) & 7) != ATOM_SRC_DWORD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) atom_skip_dst(ctx, arg, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) saved = 0xCDCDCDCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) atom_put_dst(ctx, arg, attr, &dptr, src, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) uint32_t dst, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) SDEBUG(" src1: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) SDEBUG(" src2: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ctx->ctx->divmul[0] = dst * src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static void atom_op_or(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) uint32_t dst, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) dst |= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static void atom_op_postcard(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) uint8_t val = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) SDEBUG("POST card output: 0x%02X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static void atom_op_repeat(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) pr_info("unimplemented!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static void atom_op_restorereg(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) pr_info("unimplemented!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static void atom_op_savereg(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pr_info("unimplemented!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static void atom_op_setdatablock(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int idx = U8(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) SDEBUG(" block: %d\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ctx->ctx->data_block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) else if (idx == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) ctx->ctx->data_block = ctx->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ctx->ctx->data_block = U16(ctx->ctx->data_table + 4 + 2 * idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) SDEBUG(" base: 0x%04X\n", ctx->ctx->data_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static void atom_op_setfbbase(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) SDEBUG(" fb_base: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) ctx->ctx->fb_base = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static void atom_op_setport(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) case ATOM_PORT_ATI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) port = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (port < ATOM_IO_NAMES_CNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) SDEBUG(" port: %d (%s)\n", port, atom_io_names[port]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) SDEBUG(" port: %d\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (!port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ctx->ctx->io_mode = ATOM_IO_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ctx->ctx->io_mode = ATOM_IO_IIO | port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case ATOM_PORT_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ctx->ctx->io_mode = ATOM_IO_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) case ATOM_PORT_SYSIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ctx->ctx->io_mode = ATOM_IO_SYSIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ctx->ctx->reg_block = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) uint8_t attr = U8((*ptr)++), shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) uint32_t saved, dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) attr &= 0x38;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) attr |= atom_def_dst[attr >> 3] << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) SDEBUG(" shift: %d\n", shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) dst <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) uint8_t attr = U8((*ptr)++), shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) uint32_t saved, dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) attr &= 0x38;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) attr |= atom_def_dst[attr >> 3] << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) SDEBUG(" shift: %d\n", shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) dst >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) uint8_t attr = U8((*ptr)++), shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) uint32_t saved, dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /* op needs to full dst value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) dst = saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) shift = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) SDEBUG(" shift: %d\n", shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) dst <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dst &= atom_arg_mask[dst_align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) dst >>= atom_arg_shift[dst_align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) uint8_t attr = U8((*ptr)++), shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) uint32_t saved, dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* op needs to full dst value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) dst = saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) shift = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) SDEBUG(" shift: %d\n", shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dst >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) dst &= atom_arg_mask[dst_align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) dst >>= atom_arg_shift[dst_align];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static void atom_op_sub(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) uint32_t dst, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) dst -= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static void atom_op_switch(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) uint32_t src, val, target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) SDEBUG(" switch: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) while (U16(*ptr) != ATOM_CASE_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (U8(*ptr) == ATOM_CASE_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) SDEBUG(" case: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) atom_get_src(ctx, (attr & 0x38) | ATOM_ARG_IMM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) target = U16(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (val == src) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) SDEBUG(" target: %04X\n", target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) *ptr = ctx->start + target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) pr_info("Bad case\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) (*ptr) += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static void atom_op_test(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) uint32_t dst, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) SDEBUG(" src1: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) SDEBUG(" src2: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ctx->ctx->cs_equal = ((dst & src) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) SDEBUG(" result: %s\n", ctx->ctx->cs_equal ? "EQ" : "NE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) uint8_t attr = U8((*ptr)++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) uint32_t dst, src, saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) int dptr = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) SDEBUG(" src: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) src = atom_get_src(ctx, attr, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) dst ^= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) SDEBUG(" dst: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pr_info("unimplemented!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) void (*func) (atom_exec_context *, int *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) int arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) } opcode_table[ATOM_OP_CNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) NULL, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) atom_op_move, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) atom_op_move, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) atom_op_move, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) atom_op_move, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) atom_op_move, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) atom_op_move, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) atom_op_and, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) atom_op_and, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) atom_op_and, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) atom_op_and, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) atom_op_and, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) atom_op_and, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) atom_op_or, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) atom_op_or, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) atom_op_or, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) atom_op_or, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) atom_op_or, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) atom_op_or, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) atom_op_shift_left, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) atom_op_shift_left, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) atom_op_shift_left, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) atom_op_shift_left, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) atom_op_shift_left, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) atom_op_shift_left, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) atom_op_shift_right, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) atom_op_shift_right, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) atom_op_shift_right, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) atom_op_shift_right, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) atom_op_shift_right, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) atom_op_shift_right, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) atom_op_mul, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) atom_op_mul, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) atom_op_mul, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) atom_op_mul, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) atom_op_mul, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) atom_op_mul, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) atom_op_div, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) atom_op_div, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) atom_op_div, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) atom_op_div, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) atom_op_div, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) atom_op_div, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) atom_op_add, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) atom_op_add, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) atom_op_add, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) atom_op_add, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) atom_op_add, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) atom_op_add, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) atom_op_sub, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) atom_op_sub, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) atom_op_sub, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) atom_op_sub, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) atom_op_sub, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) atom_op_sub, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) atom_op_setport, ATOM_PORT_ATI}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) atom_op_setport, ATOM_PORT_PCI}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) atom_op_setport, ATOM_PORT_SYSIO}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) atom_op_setregblock, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) atom_op_setfbbase, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) atom_op_compare, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) atom_op_compare, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) atom_op_compare, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) atom_op_compare, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) atom_op_compare, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) atom_op_compare, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) atom_op_switch, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) atom_op_jump, ATOM_COND_ALWAYS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) atom_op_jump, ATOM_COND_EQUAL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) atom_op_jump, ATOM_COND_BELOW}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) atom_op_jump, ATOM_COND_ABOVE}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) atom_op_jump, ATOM_COND_BELOWOREQUAL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) atom_op_jump, ATOM_COND_ABOVEOREQUAL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) atom_op_jump, ATOM_COND_NOTEQUAL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) atom_op_test, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) atom_op_test, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) atom_op_test, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) atom_op_test, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) atom_op_test, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) atom_op_test, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) atom_op_delay, ATOM_UNIT_MILLISEC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) atom_op_delay, ATOM_UNIT_MICROSEC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) atom_op_calltable, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) atom_op_repeat, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) atom_op_clear, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) atom_op_clear, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) atom_op_clear, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) atom_op_clear, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) atom_op_clear, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) atom_op_clear, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) atom_op_nop, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) atom_op_eot, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) atom_op_mask, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) atom_op_mask, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) atom_op_mask, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) atom_op_mask, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) atom_op_mask, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) atom_op_mask, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) atom_op_postcard, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) atom_op_beep, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) atom_op_savereg, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) atom_op_restorereg, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) atom_op_setdatablock, 0}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) atom_op_xor, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) atom_op_xor, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) atom_op_xor, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) atom_op_xor, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) atom_op_xor, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) atom_op_xor, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) atom_op_shl, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) atom_op_shl, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) atom_op_shl, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) atom_op_shl, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) atom_op_shl, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) atom_op_shl, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) atom_op_shr, ATOM_ARG_REG}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) atom_op_shr, ATOM_ARG_PS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) atom_op_shr, ATOM_ARG_WS}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) atom_op_shr, ATOM_ARG_FB}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) atom_op_shr, ATOM_ARG_PLL}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) atom_op_shr, ATOM_ARG_MC}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) atom_op_debug, 0},};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) int base = CU16(ctx->cmd_table + 4 + 2 * index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) int len, ws, ps, ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) unsigned char op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) atom_exec_context ectx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) len = CU16(base + ATOM_CT_SIZE_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ws = CU8(base + ATOM_CT_WS_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ps = CU8(base + ATOM_CT_PS_PTR) & ATOM_CT_PS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) ptr = base + ATOM_CT_CODE_PTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) ectx.ctx = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ectx.ps_shift = ps / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ectx.start = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ectx.ps = params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ectx.abort = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) ectx.last_jump = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ectx.ws = kcalloc(4, ws, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ectx.ws = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) debug_depth++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) op = CU8(ptr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (op < ATOM_OP_NAMES_CNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (ectx.abort) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) base, len, ws, ps, ptr - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (op < ATOM_OP_CNT && op > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) opcode_table[op].func(&ectx, &ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) opcode_table[op].arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (op == ATOM_OP_EOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) debug_depth--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) SDEBUG("<<\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) kfree(ectx.ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) mutex_lock(&ctx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /* reset data block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ctx->data_block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* reset reg block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ctx->reg_block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* reset fb window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ctx->fb_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* reset io mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) ctx->io_mode = ATOM_IO_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* reset divmul */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ctx->divmul[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ctx->divmul[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) r = atom_execute_table_locked(ctx, index, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) mutex_unlock(&ctx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) mutex_lock(&ctx->scratch_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) r = atom_execute_table_scratch_unlocked(ctx, index, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) mutex_unlock(&ctx->scratch_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static void atom_index_iio(struct atom_context *ctx, int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) ctx->iio = kzalloc(2 * 256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (!ctx->iio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) while (CU8(base) == ATOM_IIO_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ctx->iio[CU8(base + 1)] = base + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) base += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) while (CU8(base) != ATOM_IIO_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) base += atom_iio_len[CU8(base)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) base += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct atom_context *atom_parse(struct card_info *card, void *bios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) struct atom_context *ctx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) kzalloc(sizeof(struct atom_context), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) char name[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) ctx->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) ctx->bios = bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (CU16(0) != ATOM_BIOS_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) pr_info("Invalid BIOS magic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (strncmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) (CSTR(ATOM_ATI_MAGIC_PTR), ATOM_ATI_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) strlen(ATOM_ATI_MAGIC))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) pr_info("Invalid ATI magic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) base = CU16(ATOM_ROM_TABLE_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (strncmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) (CSTR(base + ATOM_ROM_MAGIC_PTR), ATOM_ROM_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) strlen(ATOM_ROM_MAGIC))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) pr_info("Invalid ATOM magic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (!ctx->iio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) atom_destroy(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) str = CSTR(CU16(base + ATOM_ROM_MSG_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) while (*str && ((*str == '\n') || (*str == '\r')))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* name string isn't always 0 terminated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) for (i = 0; i < 511; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) name[i] = str[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (name[i] < '.' || name[i] > 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) name[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) pr_info("ATOM BIOS: %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) int atom_asic_init(struct atom_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) struct radeon_device *rdev = ctx->card->dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) uint32_t ps[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) memset(ps, 0, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) ps[1] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFMCLK_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (!ps[0] || !ps[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) memset(ps, 0, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (rdev->family < CHIP_R600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) void atom_destroy(struct atom_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) kfree(ctx->iio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) bool atom_parse_data_header(struct atom_context *ctx, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) uint16_t * size, uint8_t * frev, uint8_t * crev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) uint16_t * data_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) int offset = index * 2 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) int idx = CU16(ctx->data_table + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (!mdt[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) *size = CU16(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (frev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) *frev = CU8(idx + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (crev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) *crev = CU8(idx + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) *data_start = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) uint8_t * crev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) int offset = index * 2 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) int idx = CU16(ctx->cmd_table + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (!mct[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (frev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) *frev = CU8(idx + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (crev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) *crev = CU8(idx + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) int atom_allocate_fb_scratch(struct atom_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) uint16_t data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) int usage_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) DRM_DEBUG("atom firmware requested %08x %dkb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) ctx->scratch_size_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (usage_bytes == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) usage_bytes = 20 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /* allocate some scratch memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if (!ctx->scratch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) ctx->scratch_size_bytes = usage_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }