1044 lines
29 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2023 Rockchip Electronics Co., Ltd. */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <media/videobuf2-cma-sg.h>
#include <media/videobuf2-dma-sg.h>
#include <soc/rockchip/rockchip_iommu.h>
#include "common.h"
#include "dev.h"
#include "hw.h"
#include "regs.h"
struct irqs_data {
const char *name;
irqreturn_t (*irq_hdl)(int irq, void *ctx);
};
const s16 rkvpss_zme_tap8_coe[11][17][8] = {
{//>=2.667
{4, -12, 20, 488, 20, -12, 4, 0},
{4, -8, 8, 484, 36, -16, 4, 0},
{4, -4, -4, 476, 52, -20, 8, 0},
{0, 0, -16, 480, 68, -28, 8, 0},
{0, 4, -24, 472, 84, -32, 8, 0},
{0, 4, -36, 468, 100, -36, 12, 0},
{0, 8, -44, 456, 120, -40, 12, 0},
{0, 12, -52, 448, 136, -44, 12, 0},
{0, 12, -56, 436, 156, -48, 16, -4},
{-4, 16, -60, 424, 176, -52, 16, -4},
{-4, 16, -64, 412, 196, -56, 16, -4},
{-4, 16, -68, 400, 216, -60, 16, -4},
{-4, 20, -72, 380, 236, -64, 20, -4},
{-4, 20, -72, 364, 256, -68, 20, -4},
{-4, 20, -72, 348, 272, -68, 20, -4},
{-4, 20, -72, 332, 292, -72, 20, -4},
{-4, 20, -72, 312, 312, -72, 20, -4},
},
{//>=2
{8, -24, 44, 456, 44, -24, 8, 0},
{8, -20, 28, 460, 56, -28, 8, 0},
{8, -16, 16, 452, 72, -32, 12, 0},
{4, -12, 8, 448, 88, -36, 12, 0},
{4, -8, -4, 444, 104, -40, 12, 0},
{4, -8, -16, 444, 120, -44, 12, 0},
{4, -4, -24, 432, 136, -48, 16, 0},
{4, 0, -32, 428, 152, -52, 16, -4},
{0, 4, -40, 424, 168, -56, 16, -4},
{0, 4, -44, 412, 188, -60, 16, -4},
{0, 8, -52, 400, 204, -60, 16, -4},
{0, 8, -56, 388, 224, -64, 16, -4},
{0, 12, -60, 372, 240, -64, 16, -4},
{0, 12, -64, 356, 264, -68, 16, -4},
{0, 12, -64, 340, 280, -68, 16, -4},
{0, 16, -68, 324, 296, -68, 16, -4},
{0, 16, -68, 308, 308, -68, 16, 0},
},
{//>=1.5
{12, -32, 64, 424, 64, -32, 12, 0},
{8, -32, 52, 432, 76, -36, 12, 0},
{8, -28, 40, 432, 88, -40, 12, 0},
{8, -24, 28, 428, 104, -44, 12, 0},
{8, -20, 16, 424, 120, -48, 12, 0},
{8, -16, 8, 416, 132, -48, 12, 0},
{4, -16, -4, 420, 148, -52, 12, 0},
{4, -12, -12, 412, 164, -56, 12, 0},
{4, -8, -20, 400, 180, -56, 12, 0},
{4, -4, -28, 388, 196, -56, 12, 0},
{4, -4, -32, 380, 212, -60, 12, 0},
{4, 0, -40, 368, 228, -60, 12, 0},
{4, 0, -44, 356, 244, -60, 12, 0},
{0, 4, -48, 344, 260, -60, 12, 0},
{0, 4, -52, 332, 276, -60, 12, 0},
{0, 8, -56, 320, 292, -60, 8, 0},
{0, 8, -56, 304, 304, -56, 8, 0},
},
{//>1
{12, -40, 84, 400, 84, -40, 12, 0},
{12, -40, 72, 404, 96, -44, 12, 0},
{12, -36, 60, 404, 108, -48, 12, 0},
{8, -32, 48, 404, 120, -48, 12, 0},
{8, -32, 36, 404, 136, -52, 12, 0},
{8, -28, 28, 396, 148, -52, 12, 0},
{8, -24, 16, 392, 160, -52, 12, 0},
{8, -20, 8, 384, 176, -56, 12, 0},
{8, -20, 0, 384, 188, -56, 8, 0},
{8, -16, -8, 372, 204, -56, 8, 0},
{8, -12, -16, 364, 216, -56, 8, 0},
{4, -12, -20, 356, 232, -56, 8, 0},
{4, -8, -28, 348, 244, -56, 8, 0},
{4, -8, -32, 332, 264, -52, 4, 0},
{4, -4, -36, 324, 272, -52, 4, 0},
{4, 0, -40, 312, 280, -48, 0, 4},
{4, 0, -44, 296, 296, -44, 0, 4},
},
{//==1
{0, 0, 0, 511, 0, 0, 0, 0},
{-1, 3, -12, 511, 14, -4, 1, 0},
{-2, 6, -23, 509, 28, -8, 2, 0},
{-2, 9, -33, 503, 44, -12, 3, 0},
{-3, 11, -41, 496, 61, -16, 4, 0},
{-3, 13, -48, 488, 79, -21, 5, -1},
{-3, 14, -54, 477, 98, -25, 7, -2},
{-4, 16, -59, 465, 118, -30, 8, -2},
{-4, 17, -63, 451, 138, -35, 9, -1},
{-4, 18, -66, 437, 158, -39, 10, -2},
{-4, 18, -68, 421, 180, -44, 11, -2},
{-4, 18, -69, 404, 201, -48, 13, -3},
{-4, 18, -70, 386, 222, -52, 14, -2},
{-4, 18, -70, 368, 244, -56, 15, -3},
{-4, 18, -69, 348, 265, -59, 16, -3},
{-4, 18, -67, 329, 286, -63, 16, -3},
{-3, 17, -65, 307, 307, -65, 17, -3},
},
{//>=0.833
{-16, 0, 145, 254, 145, 0, -16, 0},
{-16, -2, 140, 253, 151, 3, -17, 0},
{-15, -5, 135, 253, 157, 5, -18, 0},
{-14, -7, 129, 252, 162, 8, -18, 0},
{-13, -9, 123, 252, 167, 11, -19, 0},
{-13, -11, 118, 250, 172, 15, -19, 0},
{-12, -12, 112, 250, 177, 18, -20, -1},
{-11, -14, 107, 247, 183, 21, -20, -1},
{-10, -15, 101, 245, 188, 25, -21, -1},
{-9, -16, 96, 243, 192, 29, -21, -2},
{-8, -18, 90, 242, 197, 33, -22, -2},
{-8, -19, 85, 239, 202, 37, -22, -2},
{-7, -19, 80, 236, 206, 41, -22, -3},
{-7, -20, 75, 233, 210, 46, -22, -3},
{-6, -21, 69, 230, 215, 50, -22, -3},
{-5, -21, 65, 226, 219, 55, -22, -5},
{-5, -21, 60, 222, 222, 60, -21, -5},
},
{//>=0.7
{-16, 0, 145, 254, 145, 0, -16, 0},
{-16, -2, 140, 253, 151, 3, -17, 0},
{-15, -5, 135, 253, 157, 5, -18, 0},
{-14, -7, 129, 252, 162, 8, -18, 0},
{-13, -9, 123, 252, 167, 11, -19, 0},
{-13, -11, 118, 250, 172, 15, -19, 0},
{-12, -12, 112, 250, 177, 18, -20, -1},
{-11, -14, 107, 247, 183, 21, -20, -1},
{-10, -15, 101, 245, 188, 25, -21, -1},
{-9, -16, 96, 243, 192, 29, -21, -2},
{-8, -18, 90, 242, 197, 33, -22, -2},
{-8, -19, 85, 239, 202, 37, -22, -2},
{-7, -19, 80, 236, 206, 41, -22, -3},
{-7, -20, 75, 233, 210, 46, -22, -3},
{-6, -21, 69, 230, 215, 50, -22, -3},
{-5, -21, 65, 226, 219, 55, -22, -5},
{-5, -21, 60, 222, 222, 60, -21, -5},
},
{//>=0.5
{-16, 0, 145, 254, 145, 0, -16, 0},
{-16, -2, 140, 253, 151, 3, -17, 0},
{-15, -5, 135, 253, 157, 5, -18, 0},
{-14, -7, 129, 252, 162, 8, -18, 0},
{-13, -9, 123, 252, 167, 11, -19, 0},
{-13, -11, 118, 250, 172, 15, -19, 0},
{-12, -12, 112, 250, 177, 18, -20, -1},
{-11, -14, 107, 247, 183, 21, -20, -1},
{-10, -15, 101, 245, 188, 25, -21, -1},
{-9, -16, 96, 243, 192, 29, -21, -2},
{-8, -18, 90, 242, 197, 33, -22, -2},
{-8, -19, 85, 239, 202, 37, -22, -2},
{-7, -19, 80, 236, 206, 41, -22, -3},
{-7, -20, 75, 233, 210, 46, -22, -3},
{-6, -21, 69, 230, 215, 50, -22, -3},
{-5, -21, 65, 226, 219, 55, -22, -5},
{-5, -21, 60, 222, 222, 60, -21, -5},
},
{//>=0.33
{-18, 18, 144, 226, 144, 19, -17, -4},
{-17, 16, 139, 226, 148, 21, -17, -4},
{-17, 13, 135, 227, 153, 24, -18, -5},
{-17, 11, 131, 226, 157, 27, -18, -5},
{-17, 9, 126, 225, 161, 30, -17, -5},
{-16, 6, 122, 225, 165, 33, -17, -6},
{-16, 4, 118, 224, 169, 37, -17, -7},
{-16, 2, 113, 224, 173, 40, -17, -7},
{-15, 0, 109, 222, 177, 43, -17, -7},
{-15, -1, 104, 220, 181, 47, -16, -8},
{-14, -3, 100, 218, 185, 51, -16, -9},
{-14, -5, 96, 217, 188, 54, -15, -9},
{-14, -6, 91, 214, 192, 58, -14, -9},
{-13, -7, 87, 212, 195, 62, -14, -10},
{-13, -9, 83, 210, 198, 66, -13, -10},
{-12, -10, 79, 207, 201, 70, -12, -11},
{-12, -11, 74, 205, 205, 74, -11, -12},
},
{//>=0.25
{14, 66, 113, 133, 113, 66, 14, -7},
{12, 65, 112, 133, 114, 68, 15, -7},
{11, 63, 111, 132, 115, 70, 17, -7},
{10, 62, 110, 132, 116, 71, 18, -7},
{8, 60, 108, 132, 118, 73, 20, -7},
{7, 58, 107, 132, 119, 75, 21, -7},
{6, 56, 106, 132, 120, 76, 23, -7},
{5, 55, 105, 131, 121, 78, 24, -7},
{4, 53, 103, 131, 122, 80, 26, -7},
{3, 51, 102, 131, 122, 81, 28, -6},
{2, 50, 101, 130, 123, 83, 29, -6},
{1, 48, 99, 131, 124, 84, 31, -6},
{0, 46, 98, 129, 125, 86, 33, -5},
{-1, 45, 97, 128, 126, 88, 34, -5},
{-2, 43, 95, 130, 126, 89, 36, -5},
{-3, 41, 94, 128, 127, 91, 38, -4},
{-3, 39, 92, 128, 128, 92, 39, -3},
},
{//others
{39, 69, 93, 102, 93, 69, 39, 8},
{38, 68, 92, 102, 93, 70, 40, 9},
{37, 67, 91, 102, 93, 71, 41, 10},
{36, 66, 91, 101, 94, 71, 42, 11},
{35, 65, 90, 102, 94, 72, 43, 11},
{34, 64, 89, 102, 94, 73, 44, 12},
{33, 63, 88, 101, 95, 74, 45, 13},
{32, 62, 88, 100, 95, 75, 46, 14},
{31, 62, 87, 100, 95, 75, 47, 15},
{30, 61, 86, 99, 96, 76, 48, 16},
{29, 60, 86, 98, 96, 77, 49, 17},
{28, 59, 85, 98, 96, 78, 50, 18},
{27, 58, 84, 99, 97, 78, 50, 19},
{26, 57, 83, 99, 97, 79, 51, 20},
{25, 56, 83, 98, 97, 80, 52, 21},
{24, 55, 82, 97, 98, 81, 53, 22},
{23, 54, 81, 98, 98, 81, 54, 23},
}
};
const s16 rkvpss_zme_tap6_coe[11][17][8] = {
{//>=2.667
{-12, 20, 492, 20, -12, 4, 0, 0},
{-8, 8, 488, 36, -16, 4, 0, 0},
{-4, -4, 488, 48, -20, 4, 0, 0},
{0, -16, 484, 64, -24, 4, 0, 0},
{0, -24, 476, 80, -28, 8, 0, 0},
{4, -32, 464, 100, -32, 8, 0, 0},
{8, -40, 456, 116, -36, 8, 0, 0},
{8, -48, 448, 136, -40, 8, 0, 0},
{12, -52, 436, 152, -44, 8, 0, 0},
{12, -60, 424, 172, -48, 12, 0, 0},
{12, -64, 412, 192, -52, 12, 0, 0},
{16, -64, 392, 212, -56, 12, 0, 0},
{16, -68, 380, 232, -60, 12, 0, 0},
{16, -68, 360, 248, -60, 16, 0, 0},
{16, -68, 344, 268, -64, 16, 0, 0},
{16, -68, 328, 288, -68, 16, 0, 0},
{16, -68, 308, 308, -68, 16, 0, 0},
},
{//>=2
{-20, 40, 468, 40, -20, 4, 0, 0},
{-16, 28, 464, 56, -24, 4, 0, 0},
{-16, 16, 464, 68, -28, 8, 0, 0},
{-12, 4, 460, 84, -32, 8, 0, 0},
{-8, -4, 452, 100, -36, 8, 0, 0},
{-4, -12, 444, 116, -40, 8, 0, 0},
{-4, -24, 440, 136, -44, 8, 0, 0},
{0, -32, 432, 152, -48, 8, 0, 0},
{0, -36, 416, 168, -48, 12, 0, 0},
{4, -44, 408, 184, -52, 12, 0, 0},
{4, -48, 400, 200, -56, 12, 0, 0},
{8, -52, 380, 220, -56, 12, 0, 0},
{8, -56, 372, 236, -60, 12, 0, 0},
{8, -60, 356, 256, -60, 12, 0, 0},
{12, -60, 340, 268, -60, 12, 0, 0},
{12, -60, 324, 288, -64, 12, 0, 0},
{12, -64, 308, 308, -64, 12, 0, 0},
},
{//>=1.5
{-28, 60, 440, 60, -28, 8, 0, 0},
{-28, 48, 440, 76, -32, 8, 0, 0},
{-24, 36, 440, 88, -36, 8, 0, 0},
{-20, 28, 432, 104, -40, 8, 0, 0},
{-16, 16, 428, 116, -40, 8, 0, 0},
{-16, 4, 428, 132, -44, 8, 0, 0},
{-12, -4, 420, 148, -48, 8, 0, 0},
{-8, -12, 408, 164, -48, 8, 0, 0},
{-8, -20, 404, 180, -52, 8, 0, 0},
{-4, -24, 388, 196, -52, 8, 0, 0},
{-4, -32, 384, 212, -56, 8, 0, 0},
{0, -36, 372, 224, -56, 8, 0, 0},
{0, -40, 360, 240, -56, 8, 0, 0},
{4, -44, 344, 256, -56, 8, 0, 0},
{4, -48, 332, 272, -56, 8, 0, 0},
{4, -52, 316, 292, -56, 8, 0, 0},
{8, -52, 300, 300, -52, 8, 0, 0},
},
{//>1
{-36, 80, 420, 80, -36, 4, 0, 0},
{-32, 68, 412, 92, -36, 8, 0, 0},
{-28, 56, 412, 104, -40, 8, 0, 0},
{-28, 44, 412, 116, -40, 8, 0, 0},
{-24, 36, 404, 132, -44, 8, 0, 0},
{-24, 24, 404, 144, -44, 8, 0, 0},
{-20, 16, 396, 160, -48, 8, 0, 0},
{-16, 8, 388, 172, -48, 8, 0, 0},
{-16, 0, 380, 188, -48, 8, 0, 0},
{-12, -8, 376, 200, -48, 4, 0, 0},
{-12, -12, 364, 216, -48, 4, 0, 0},
{-8, -20, 356, 228, -48, 4, 0, 0},
{-8, -24, 344, 244, -48, 4, 0, 0},
{-4, -32, 332, 260, -48, 4, 0, 0},
{-4, -36, 320, 272, -44, 4, 0, 0},
{0, -40, 308, 288, -44, 0, 0, 0},
{0, -40, 296, 296, -40, 0, 0, 0},
},
{//==1
{0, 0, 511, 0, 0, 0, 0, 0},
{3, -12, 511, 13, -3, 0, 0, 0},
{6, -22, 507, 28, -7, 0, 0, 0},
{8, -32, 502, 44, -11, 1, 0, 0},
{10, -40, 495, 61, -15, 1, 0, 0},
{11, -47, 486, 79, -19, 2, 0, 0},
{12, -53, 476, 98, -24, 3, 0, 0},
{13, -58, 464, 117, -28, 4, 0, 0},
{14, -62, 451, 137, -33, 5, 0, 0},
{15, -65, 437, 157, -38, 6, 0, 0},
{15, -67, 420, 179, -42, 7, 0, 0},
{15, -68, 404, 200, -46, 7, 0, 0},
{14, -68, 386, 221, -50, 9, 0, 0},
{14, -68, 367, 243, -54, 10, 0, 0},
{14, -67, 348, 264, -58, 11, 0, 0},
{13, -66, 328, 286, -61, 12, 0, 0},
{13, -63, 306, 306, -63, 13, 0, 0},
},
{//>=0.833
{-31, 104, 362, 104, -31, 4, 0, 0},
{-30, 94, 362, 114, -32, 4, 0, 0},
{-29, 84, 361, 125, -32, 3, 0, 0},
{-28, 75, 359, 136, -33, 3, 0, 0},
{-27, 66, 356, 147, -33, 3, 0, 0},
{-25, 57, 353, 158, -33, 2, 0, 0},
{-24, 49, 349, 169, -33, 2, 0, 0},
{-22, 41, 344, 180, -32, 1, 0, 0},
{-20, 33, 339, 191, -31, 0, 0, 0},
{-19, 26, 333, 203, -30, -1, 0, 0},
{-17, 19, 327, 214, -29, -2, 0, 0},
{-16, 13, 320, 225, -27, -3, 0, 0},
{-14, 7, 312, 236, -25, -4, 0, 0},
{-13, 1, 305, 246, -22, -5, 0, 0},
{-11, -4, 295, 257, -19, -6, 0, 0},
{-10, -8, 286, 267, -16, -7, 0, 0},
{-9, -12, 277, 277, -12, -9, 0, 0},
},
{//>=0.7
{-31, 104, 362, 104, -31, 4, 0, 0},
{-30, 94, 362, 114, -32, 4, 0, 0},
{-29, 84, 361, 125, -32, 3, 0, 0},
{-28, 75, 359, 136, -33, 3, 0, 0},
{-27, 66, 356, 147, -33, 3, 0, 0},
{-25, 57, 353, 158, -33, 2, 0, 0},
{-24, 49, 349, 169, -33, 2, 0, 0},
{-22, 41, 344, 180, -32, 1, 0, 0},
{-20, 33, 339, 191, -31, 0, 0, 0},
{-19, 26, 333, 203, -30, -1, 0, 0},
{-17, 19, 327, 214, -29, -2, 0, 0},
{-16, 13, 320, 225, -27, -3, 0, 0},
{-14, 7, 312, 236, -25, -4, 0, 0},
{-13, 1, 305, 246, -22, -5, 0, 0},
{-11, -4, 295, 257, -19, -6, 0, 0},
{-10, -8, 286, 267, -16, -7, 0, 0},
{-9, -12, 277, 277, -12, -9, 0, 0},
},
{//>=0.5
{ -20, 130, 297, 130, -20, -5, 0, 0},
{ -21, 122, 298, 138, -19, -6, 0, 0},
{ -22, 115, 297, 146, -17, -7, 0, 0},
{ -22, 108, 296, 153, -16, -7, 0, 0},
{ -23, 101, 295, 161, -14, -8, 0, 0},
{ -23, 93, 294, 169, -12, -9, 0, 0},
{ -24, 87, 292, 177, -10, -10, 0, 0},
{ -24, 80, 289, 185, -7, -11, 0, 0},
{ -24, 73, 286, 193, -4, -12, 0, 0},
{ -23, 66, 283, 200, -1, -13, 0, 0},
{ -23, 60, 279, 208, 2, -14, 0, 0},
{ -23, 54, 276, 215, 5, -15, 0, 0},
{ -22, 48, 271, 222, 9, -16, 0, 0},
{ -21, 42, 266, 229, 13, -17, 0, 0},
{ -21, 37, 261, 236, 17, -18, 0, 0},
{ -21, 32, 255, 242, 22, -18, 0, 0},
{ -20, 27, 249, 249, 27, -20, 0, 0},
},
{//>=0.33
{16, 136, 217, 136, 16, -9, 0, 0},
{13, 132, 217, 141, 18, -9, 0, 0},
{11, 128, 217, 145, 21, -10, 0, 0},
{9, 124, 216, 149, 24, -10, 0, 0},
{7, 119, 216, 153, 27, -10, 0, 0},
{5, 115, 216, 157, 30, -11, 0, 0},
{3, 111, 215, 161, 33, -11, 0, 0},
{1, 107, 214, 165, 36, -11, 0, 0},
{0, 102, 213, 169, 39, -11, 0, 0},
{-2, 98, 211, 173, 43, -11, 0, 0},
{-3, 94, 209, 177, 46, -11, 0, 0},
{-4, 90, 207, 180, 50, -11, 0, 0},
{-5, 85, 206, 184, 53, -11, 0, 0},
{-6, 81, 203, 187, 57, -10, 0, 0},
{-7, 77, 201, 190, 61, -10, 0, 0},
{-8, 73, 198, 193, 65, -9, 0, 0},
{-9, 69, 196, 196, 69, -9, 0, 0},
},
{//>=0.25
{66, 115, 138, 115, 66, 12, 0, 0},
{64, 114, 136, 116, 68, 14, 0, 0},
{63, 113, 134, 117, 70, 15, 0, 0},
{61, 111, 135, 118, 71, 16, 0, 0},
{59, 110, 133, 119, 73, 18, 0, 0},
{57, 108, 134, 120, 74, 19, 0, 0},
{55, 107, 133, 121, 76, 20, 0, 0},
{53, 105, 133, 121, 78, 22, 0, 0},
{51, 104, 133, 122, 79, 23, 0, 0},
{49, 102, 132, 123, 81, 25, 0, 0},
{47, 101, 132, 124, 82, 26, 0, 0},
{45, 99, 131, 125, 84, 28, 0, 0},
{44, 98, 130, 125, 85, 30, 0, 0},
{42, 96, 130, 126, 87, 31, 0, 0},
{40, 95, 128, 127, 89, 33, 0, 0},
{38, 93, 129, 127, 90, 35, 0, 0},
{36, 92, 128, 128, 92, 36, 0, 0},
},
{//others
{80, 105, 116, 105, 80, 26, 0, 0},
{79, 104, 115, 105, 81, 28, 0, 0},
{77, 103, 116, 106, 81, 29, 0, 0},
{76, 102, 115, 106, 82, 31, 0, 0},
{74, 101, 115, 106, 83, 33, 0, 0},
{73, 100, 114, 106, 84, 35, 0, 0},
{71, 99, 114, 107, 84, 37, 0, 0},
{70, 98, 113, 107, 85, 39, 0, 0},
{68, 98, 113, 107, 86, 40, 0, 0},
{67, 97, 112, 108, 86, 42, 0, 0},
{65, 96, 112, 108, 87, 44, 0, 0},
{63, 95, 112, 108, 88, 46, 0, 0},
{62, 94, 112, 108, 88, 48, 0, 0},
{60, 93, 111, 109, 89, 50, 0, 0},
{58, 93, 111, 109, 90, 51, 0, 0},
{57, 92, 110, 110, 90, 53, 0, 0},
{55, 91, 110, 110, 91, 55, 0, 0},
}
};
void rkvpss_hw_write(struct rkvpss_hw_dev *hw, u32 reg, u32 val)
{
unsigned long lock_flags = 0;
if (IS_SYNC_REG(reg))
spin_lock_irqsave(&hw->reg_lock, lock_flags);
writel(val, hw->base_addr + reg);
if (IS_SYNC_REG(reg))
spin_unlock_irqrestore(&hw->reg_lock, lock_flags);
}
u32 rkvpss_hw_read(struct rkvpss_hw_dev *hw, u32 reg)
{
unsigned long lock_flags = 0;
u32 val;
if (IS_SYNC_REG(reg))
spin_lock_irqsave(&hw->reg_lock, lock_flags);
val = readl(hw->base_addr + reg);
if (IS_SYNC_REG(reg))
spin_unlock_irqrestore(&hw->reg_lock, lock_flags);
return val;
}
void rkvpss_hw_set_bits(struct rkvpss_hw_dev *hw, u32 reg, u32 mask, u32 val)
{
unsigned long lock_flags = 0;
u32 tmp;
if (IS_SYNC_REG(reg))
spin_lock_irqsave(&hw->reg_lock, lock_flags);
tmp = readl(hw->base_addr + reg) & ~mask;
writel(val | tmp, hw->base_addr + reg);
if (IS_SYNC_REG(reg))
spin_unlock_irqrestore(&hw->reg_lock, lock_flags);
}
void rkvpss_hw_clear_bits(struct rkvpss_hw_dev *hw, u32 reg, u32 mask)
{
unsigned long lock_flags = 0;
u32 val;
if (IS_SYNC_REG(reg))
spin_lock_irqsave(&hw->reg_lock, lock_flags);
val = readl(hw->base_addr + reg) & ~mask;
writel(val, hw->base_addr + reg);
if (IS_SYNC_REG(reg))
spin_unlock_irqrestore(&hw->reg_lock, lock_flags);
}
void rkvpss_soft_reset(struct rkvpss_hw_dev *hw)
{
writel(RKVPSS_SOFT_RST, hw->base_addr + RKVPSS_VPSS_RESET);
if (hw->reset) {
reset_control_assert(hw->reset);
udelay(20);
reset_control_deassert(hw->reset);
udelay(20);
}
/* refresh iommu after reset */
if (hw->is_mmu) {
rockchip_iommu_disable(hw->dev);
rockchip_iommu_enable(hw->dev);
}
rkvpss_hw_set_bits(hw, RKVPSS_VPSS_CTRL, RKVPSS_ACK_FRM_PRO_DIS,
RKVPSS_ACK_FRM_PRO_DIS);
rkvpss_hw_write(hw, RKVPSS_VPSS_IRQ_CFG, 0x3fff);
rkvpss_hw_write(hw, RKVPSS_MI_IMSC, 0xd0000000);
rkvpss_hw_set_bits(hw, RKVPSS_VPSS_ONLINE, RKVPSS_ONLINE_MODE_MASK,
RKVPSS_ISP2VPSS_ONLINE2);
rkvpss_hw_write(hw, RKVPSS_VPSS_UPDATE, RKVPSS_CFG_FORCE_UPD);
}
int rkvpss_get_zme_tap_coe_index(int ratio)
{
int idx;
if (ratio >= 26670)
idx = 0;
else if (ratio >= 20000)
idx = 1;
else if (ratio >= 15000)
idx = 2;
else if (ratio > 10000)
idx = 3;
else if (ratio == 10000)
idx = 4;
else if (ratio >= 8333)
idx = 5;
else if (ratio >= 7000)
idx = 6;
else if (ratio >= 5000)
idx = 7;
else if (ratio >= 3300)
idx = 8;
else if (ratio >= 2500)
idx = 9;
else
idx = 10;
return idx;
}
void rkvpss_cmsc_slop(struct rkvpss_cmsc_point *p0,
struct rkvpss_cmsc_point *p1,
int *k, int *hor)
{
int x0 = p0->x, y0 = p0->y;
int x1 = p1->x, y1 = p1->y;
int i, slp, sign_flag = 0, slp_bit = 13;
int highest1 = 0, k_fix, pow;
if (y0 == y1) {
/* horizontal line */
*hor = 1;
slp = 0;
} else {
*hor = 0;
slp = (int)((x1 - x0) * (1 << slp_bit) / (y1 - y0));
if (slp < 0) {
sign_flag = 1;
slp = -slp;
}
slp = min_t(int, slp, (1 << slp_bit * 2) - 1);
}
for (i = slp_bit * 2 - 1; i >= 0; i--) {
if (slp >> i) {
highest1 = i;
break;
}
}
if (highest1 >= slp_bit) {
pow = highest1 - slp_bit + 1;
k_fix = slp >> pow;
} else {
pow = 0;
k_fix = slp;
}
*k = (sign_flag << (slp_bit + 4)) + (pow << slp_bit) + k_fix;
}
static inline bool is_iommu_enable(struct device *dev)
{
struct device_node *iommu;
iommu = of_parse_phandle(dev->of_node, "iommus", 0);
if (!iommu) {
dev_info(dev, "no iommu attached, using non-iommu buffers\n");
return false;
} else if (!of_device_is_available(iommu)) {
dev_info(dev, "iommu is disabled, using non-iommu buffers\n");
of_node_put(iommu);
return false;
}
of_node_put(iommu);
return true;
}
static void disable_sys_clk(struct rkvpss_hw_dev *dev)
{
int i;
for (i = 0; i < dev->clks_num; i++)
clk_disable_unprepare(dev->clks[i]);
}
static int enable_sys_clk(struct rkvpss_hw_dev *dev)
{
int i, ret = -EINVAL;
for (i = 0; i < dev->clks_num; i++) {
ret = clk_prepare_enable(dev->clks[i]);
if (ret < 0)
goto err;
}
return 0;
err:
for (--i; i >= 0; --i)
clk_disable_unprepare(dev->clks[i]);
return ret;
}
static irqreturn_t vpss_irq_hdl(int irq, void *ctx)
{
struct device *dev = ctx;
struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev);
struct rkvpss_device *vpss = hw_dev->vpss[hw_dev->cur_dev_id];
unsigned int mis_val;
mis_val = rkvpss_hw_read(hw_dev, RKVPSS_VPSS_MIS);
if (mis_val) {
rkvpss_hw_write(hw_dev, RKVPSS_VPSS_ICR, mis_val);
if (mis_val & RKVPSS_ISP_ALL_FRM_END)
rkvpss_isr(vpss, mis_val);
if (mis_val & RKVPSS_ALL_FRM_END)
rkvpss_offline_irq(hw_dev, mis_val);
}
return IRQ_HANDLED;
}
static irqreturn_t mi_irq_hdl(int irq, void *ctx)
{
struct device *dev = ctx;
struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev);
struct rkvpss_device *vpss = hw_dev->vpss[hw_dev->cur_dev_id];
unsigned int mis_val;
mis_val = rkvpss_hw_read(hw_dev, RKVPSS_MI_MIS);
if (mis_val) {
if (mis_val & RKVPSS_MI_BUS_ERR)
dev_err(dev, "axi bus error\n");
rkvpss_hw_write(hw_dev, RKVPSS_MI_ICR, mis_val);
if (vpss)
rkvpss_mi_isr(vpss, mis_val);
}
return IRQ_HANDLED;
}
static struct irqs_data vpss_irqs[] = {
{"vpss_irq", vpss_irq_hdl},
{"mi_irq", mi_irq_hdl},
};
static const char * const vpss_clks[] = {
"clk_vpss",
"aclk_vpss",
"hclk_vpss",
};
static const struct vpss_match_data rk3576_vpss_match_data = {
.irqs = vpss_irqs,
.num_irqs = ARRAY_SIZE(vpss_irqs),
.clks = vpss_clks,
.clks_num = ARRAY_SIZE(vpss_clks),
.vpss_ver = VPSS_V10,
};
static const struct of_device_id rkvpss_hw_of_match[] = {
{
.compatible = "rockchip,rk3576-rkvpss",
.data = &rk3576_vpss_match_data,
},
{},
};
void rkvpss_hw_reg_save(struct rkvpss_hw_dev *dev)
{
void *buf = dev->sw_reg;
dev_info(dev->dev, "%s\n", __func__);
memcpy_fromio(buf, dev->base_addr, RKVPSS_SW_REG_SIZE);
}
void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev)
{
void __iomem *base = dev->base_addr;
void *reg_buf = dev->sw_reg;
u32 val, *reg, i;
dev_info(dev->dev, "%s\n", __func__);
/* cmsc */
for (i = RKVPSS_CMSC_BASE; i <= RKVPSS_CMSC_WIN7_L3_SLP; i += 4) {
if (i == RKVPSS_CMSC_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_CMSC_GEN_UPD | RKVPSS_CMSC_UPDATE;
writel(val, base + RKVPSS_CMSC_UPDATE);
/* crop1 */
for (i = RKVPSS_CROP1_CTRL; i <= RKVPSS_CROP1_3_V_SIZE; i += 4) {
if (i == RKVPSS_CROP1_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_CROP_GEN_UPD | RKVPSS_CROP_FORCE_UPD;
writel(val, base + RKVPSS_CROP1_UPDATE);
writel(val, base + RKVPSS_CROP1_UPDATE);
/* scale */
for (i = RKVPSS_ZME_BASE; i <= RKVPSS_ZME_UV_YSCL_FACTOR; i += 4) {
if (i == RKVPSS_ZME_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_ZME_GEN_UPD | RKVPSS_ZME_FORCE_UPD;
writel(val, base + RKVPSS_ZME_UPDATE);
for (i = RKVPSS_SCALE1_BASE; i <= RKVPSS_SCALE1_IN_CROP_OFFSET; i += 4) {
if (i == RKVPSS_SCALE1_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS_SCALE1_UPDATE);
for (i = RKVPSS_SCALE2_BASE; i <= RKVPSS_SCALE2_IN_CROP_OFFSET; i += 4) {
if (i == RKVPSS_SCALE2_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS_SCALE2_UPDATE);
for (i = RKVPSS_SCALE3_BASE; i <= RKVPSS_SCALE3_IN_CROP_OFFSET; i += 4) {
if (i == RKVPSS_SCALE3_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS_SCALE3_UPDATE);
/* mi */
for (i = RKVPSS_MI_BASE; i <= RKVPSS_MI_CHN3_WR_LINE_CNT; i += 4) {
if (i >= RKVPSS_MI_RD_CTRL && i <= RKVPSS_MI_RD_Y_HEIGHT_SHD)
continue;
if (i == RKVPSS_MI_WR_INIT)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_MI_FORCE_UPD;
writel(val, base + RKVPSS_MI_WR_INIT);
writel(val, base + RKVPSS_MI_WR_INIT);
/* vpss ctrl */
for (i = RKVPSS_VPSS_BASE; i <= RKVPSS_VPSS_Y2R_OFF2; i += 4) {
if (i == RKVPSS_VPSS_UPDATE || i == RKVPSS_VPSS_RESET)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_CFG_FORCE_UPD | RKVPSS_CFG_GEN_UPD | RKVPSS_MIR_GEN_UPD |
RKVPSS_ONLINE2_CHN_FORCE_UPD;
if (!dev->is_ofl_cmsc)
val |= RKVPSS_MIR_FORCE_UPD;
writel(val, base + RKVPSS_VPSS_UPDATE);
}
static int rkvpss_hw_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct vpss_match_data *match_data;
struct device_node *node = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct rkvpss_hw_dev *hw_dev;
struct resource *res;
int i, ret, irq;
bool is_mem_reserved = true;
match = of_match_node(rkvpss_hw_of_match, node);
if (IS_ERR(match))
return PTR_ERR(match);
hw_dev = devm_kzalloc(dev, sizeof(*hw_dev), GFP_KERNEL);
if (!hw_dev)
return -ENOMEM;
hw_dev->sw_reg = devm_kzalloc(dev, RKVPSS_SW_REG_SIZE, GFP_KERNEL);
if (!hw_dev->sw_reg)
return -ENOMEM;
dev_set_drvdata(dev, hw_dev);
hw_dev->dev = dev;
match_data = match->data;
hw_dev->match_data = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "get resource failed\n");
ret = -EINVAL;
goto err;
}
hw_dev->base_addr = devm_ioremap_resource(dev, res);
if (PTR_ERR(hw_dev->base_addr) == -EBUSY) {
resource_size_t offset = res->start;
resource_size_t size = resource_size(res);
hw_dev->base_addr = devm_ioremap(dev, offset, size);
}
if (IS_ERR(hw_dev->base_addr)) {
dev_err(dev, "ioremap failed\n");
ret = PTR_ERR(hw_dev->base_addr);
goto err;
}
for (i = 0; i < match_data->num_irqs; i++) {
irq = platform_get_irq_byname(pdev, match_data->irqs[i].name);
if (irq < 0) {
dev_err(dev, "no irq %s in dts\n", match_data->irqs[i].name);
ret = irq;
goto err;
}
ret = devm_request_irq(dev, irq,
match_data->irqs[i].irq_hdl,
IRQF_SHARED,
dev_driver_string(dev),
dev);
if (ret < 0) {
dev_err(dev, "request %s failed: %d\n",
match_data->irqs[i].name, ret);
goto err;
}
}
for (i = 0; i < match_data->clks_num; i++) {
struct clk *clk = devm_clk_get(dev, match_data->clks[i]);
if (IS_ERR(clk)) {
dev_err(dev, "failed to get %s\n",
match_data->clks[i]);
ret = PTR_ERR(clk);
goto err;
}
hw_dev->clks[i] = clk;
}
hw_dev->clks_num = match_data->clks_num;
hw_dev->reset = devm_reset_control_array_get(dev, false, false);
if (IS_ERR(hw_dev->reset)) {
dev_info(dev, "failed to get cru reset\n");
hw_dev->reset = NULL;
}
hw_dev->dev_num = 0;
hw_dev->cur_dev_id = 0;
hw_dev->pre_dev_id = -1;
hw_dev->vpss_ver = match_data->vpss_ver;
mutex_init(&hw_dev->dev_lock);
spin_lock_init(&hw_dev->reg_lock);
atomic_set(&hw_dev->refcnt, 0);
INIT_LIST_HEAD(&hw_dev->list);
for (i = 0; i < RKVPSS_OUTPUT_MAX; i++)
hw_dev->is_ofl_ch[i] = false;
hw_dev->is_ofl_cmsc = false;
hw_dev->is_single = true;
hw_dev->is_dma_contig = true;
hw_dev->is_shutdown = false;
hw_dev->is_mmu = is_iommu_enable(dev);
hw_dev->is_suspend = false;
ret = of_reserved_mem_device_init(dev);
if (ret) {
is_mem_reserved = false;
if (!hw_dev->is_mmu)
dev_info(dev, "No reserved memory region. default cma area!\n");
}
if (hw_dev->is_mmu && !is_mem_reserved)
hw_dev->is_dma_contig = false;
hw_dev->mem_ops = &vb2_cma_sg_memops;
rkvpss_register_offline(hw_dev);
pm_runtime_enable(&pdev->dev);
return 0;
err:
return ret;
}
static int rkvpss_hw_remove(struct platform_device *pdev)
{
struct rkvpss_hw_dev *hw_dev = platform_get_drvdata(pdev);
rkvpss_unregister_offline(hw_dev);
pm_runtime_disable(&pdev->dev);
mutex_destroy(&hw_dev->dev_lock);
return 0;
}
static void rkvpss_hw_shutdown(struct platform_device *pdev)
{
struct rkvpss_hw_dev *hw_dev = platform_get_drvdata(pdev);
hw_dev->is_shutdown = true;
if (pm_runtime_active(&pdev->dev)) {
rkvpss_hw_write(hw_dev, RKVPSS_VPSS_IMSC, 0);
rkvpss_hw_write(hw_dev, RKVPSS_MI_IMSC, 0);
rkvpss_hw_write(hw_dev, RKVPSS_VPSS_RESET, RKVPSS_SOFT_RST);
}
}
static int __maybe_unused rkvpss_hw_runtime_suspend(struct device *dev)
{
struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev);
u32 ret;
if (rkvpss_debug >= 4)
dev_info(dev, "%s enter\n", __func__);
if (dev->power.runtime_status) {
rkvpss_hw_write(hw_dev, RKVPSS_MI_IMSC, 0);
rkvpss_hw_write(hw_dev, RKVPSS_VPSS_IMSC, 0);
hw_dev->ofl_dev.mode_sel_en = true;
} else {
rkvpss_hw_reg_save(hw_dev);
hw_dev->is_suspend = true;
if (hw_dev->ofl_dev.pm_need_wait) {
ret = wait_for_completion_timeout(&hw_dev->ofl_dev.pm_cmpl,
msecs_to_jiffies(200));
if (!ret)
dev_info(dev, "%s pm wait offline timeout\n", __func__);
}
}
disable_sys_clk(hw_dev);
if (rkvpss_debug >= 4)
dev_info(dev, "%s exit\n", __func__);
return 0;
}
static int __maybe_unused rkvpss_hw_runtime_resume(struct device *dev)
{
struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev);
void __iomem *base = hw_dev->base_addr;
int i;
if (rkvpss_debug >= 4)
dev_info(dev, "%s enter\n", __func__);
enable_sys_clk(hw_dev);
rkvpss_soft_reset(hw_dev);
if (dev->power.runtime_status) {
for (i = 0; i < hw_dev->dev_num; i++) {
void *buf = hw_dev->vpss[i]->sw_base_addr;
memset(buf, 0, RKVPSS_SW_REG_SIZE_MAX);
memcpy_fromio(buf, base, RKVPSS_SW_REG_SIZE);
}
} else {
rkvpss_hw_reg_restore(hw_dev);
hw_dev->is_suspend = false;
}
if (rkvpss_debug >= 4)
dev_info(dev, "%s exit\n", __func__);
return 0;
}
static const struct dev_pm_ops rkvpss_hw_pm_ops = {
LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(rkvpss_hw_runtime_suspend,
rkvpss_hw_runtime_resume, NULL)
};
static struct platform_driver rkvpss_hw_drv = {
.driver = {
.name = "rkvpss_hw",
.of_match_table = of_match_ptr(rkvpss_hw_of_match),
.pm = &rkvpss_hw_pm_ops,
},
.probe = rkvpss_hw_probe,
.remove = rkvpss_hw_remove,
.shutdown = rkvpss_hw_shutdown,
};
static int __init rkvpss_hw_drv_init(void)
{
int ret;
ret = platform_driver_register(&rkvpss_hw_drv);
if (!ret)
ret = platform_driver_register(&rkvpss_plat_drv);
return ret;
}
static void __exit rkvpss_hw_drv_exit(void)
{
platform_driver_unregister(&rkvpss_plat_drv);
platform_driver_unregister(&rkvpss_hw_drv);
}
module_init(rkvpss_hw_drv_init);
module_exit(rkvpss_hw_drv_exit);