# Copyright (c) 2016, 2018, 2020 The Linux Foundation. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
from parser_util import register_parser, RamParser
from print_out import print_out_str
from linux_list import ListWalker
from ramdump import Struct
import sys
import re
import string
import os
from os import path
import fileinput
import time
class MdssDbgBase(Struct):
_struct_name = "struct mdss_debug_base"
_fields = {
'name': Struct.get_cstring,
'base': Struct.get_pointer,
'max_offset': Struct.get_u32,
'dump_list': Struct.get_address,
'reg_dump': Struct.get_pointer,
}
class MdssDbgXlog(Struct):
def get_dbgbase_arr(self, key):
arr = self.get_array_ptrs(key)
return [MdssDbgBase(self.ramdump, b) for b in arr]
_struct_name = "struct mdss_dbg_xlog"
_fields = {
'blk_arr': get_dbgbase_arr,
}
class SdeDbgBase(Struct):
_struct_name = "struct sde_dbg_base"
_fields = {
'evtlog': Struct.get_pointer,
'reg_base_list': Struct.get_pointer,
'enable_reg_dump' : Struct.get_u32,
'panic_on_err' : Struct.get_u32,
}
class RangeDumpFbNode(Struct):
def get_offset(self, key):
return Struct(self.ramdump, self.get_address(key),
struct_name="struct dump_offset",
fields={
'start': Struct.get_u32,
'end': Struct.get_u32,
})
_struct_name = "struct range_dump_node"
_fields = {
'offset': get_offset,
'range_name': Struct.get_cstring,
'reg_dump': Struct.get_pointer,
}
class RangeDumpSdeNode(Struct):
def get_offset(self, key):
return Struct(self.ramdump, self.get_address(key),
struct_name="struct sde_dbg_reg_offset",
fields={
'start': Struct.get_u32,
'end': Struct.get_u32,
})
_struct_name = "struct sde_dbg_reg_range"
_fields = {
'offset': get_offset,
'range_name': Struct.get_cstring,
'reg_dump': Struct.get_pointer,
}
def get_u64(self, key):
address = self.get_address(key)
return self.ramdump.read_u64(address)
@register_parser('--print-mdssinfo', 'print mdss info')
class MDPinfo(RamParser):
def __init__(self, *args):
super(MDPinfo, self).__init__(*args)
self.outfile = None
self.optionalfile = 0
self.prev_timestamp_rd_ptr = -1
self.prev_timestamp_vsync_irq = -1
self.log_1 = -1
self.log_2 = -1
self.log_3 = -1
self.log_4 = -1
self.sde_dbg_evtlog_log_optional = []
self.counter = 0
self.ctl_flag = 0
self.vbif_flag = 0
def BIT(self, val):
return (1 << val)
def mdss_dump_reg(self, addr, length, reg_dump, offset):
if reg_dump == 0:
return
# Making length multiple of 16
length = int((length + 15) / 16)
base = addr
# Print out registers
for i in range(0, length):
self.outfile.write('0x{0:x}| '.format(addr-base+offset, 10))
for j in range(0, 4):
read = reg_dump + (16 * i) + (4 * j)
self.outfile.write('{0:08x} '
.format(self.ramdump.read_u32(read), 10))
self.outfile.write('\n')
addr += 16
def print_range(self, blk, node):
rng = RangeDumpFbNode(self.ramdump, node)
if (rng.offset.start > rng.offset.end) or (rng.offset.end == 0):
print_out_str("Invalid offsets (%d, %d) for range: %s" %
(rng.offset.start, rng.offset.end, rng.range_name))
return
addr = blk.base + rng.offset.start
self.outfile.write('{0}: base=0x{1:x} start=0x{2:x} end=0x{3:x}\n'
.format(rng.range_name, addr,
rng.offset.start, rng.offset.end))
self.outfile.write('start_addr:{0:x} end_addr:{1:x} reg_addr={2:x}\n'
.format(rng.offset.start, rng.offset.end, addr))
# Calculating length
length = min(blk.max_offset, rng.offset.end) - rng.offset.start
self.mdss_dump_reg(addr, length, rng.reg_dump, rng.offset.start)
def print_sderange(self, node):
rng = RangeDumpSdeNode(self.ramdump, node)
if (rng.offset.start > rng.offset.end) or (rng.offset.end == 0):
print_out_str("Invalid offsets (%d, %d) for range: %s" %
(rng.offset.start, rng.offset.end, rng.range_name))
return
addr = node + rng.offset.start
self.outfile.write('\n---------------------------------------------------------------------\n')
self.outfile.write('[{0}] 0x{1:x}\n'.format(rng.range_name, rng.offset.start))
self.outfile.write('---------------------------------------------------------------------\n')
# Calculating length
length = rng.offset.end - rng.offset.start
self.mdss_dump_reg(addr, length, rng.reg_dump, rng.offset.start)
def default_parse(self, sde_dbg_evtlog_log_, output_fd) :
line_new = '{:<54}{:<29}{:<6}{:<3}{:<200}'.format(sde_dbg_evtlog_log_["fun_name"]+":"+str(sde_dbg_evtlog_log_["line_number"]), "==>"+str(sde_dbg_evtlog_log_["timestamp"])+": "+str(sde_dbg_evtlog_log_["time_diff"]), "["+sde_dbg_evtlog_log_["pid"]+"]","["+sde_dbg_evtlog_log_["cpu"]+"]",sde_dbg_evtlog_log_["data"])
self.outfile.write(line_new)
self.outfile.write("\n")
def decode_dsi_ctrl_isr(self, sde_dbg_evtlog_log_, output_fd):
xlog_data = str(sde_dbg_evtlog_log_["data"])
data = xlog_data.split(" ")
tmp = xlog_data
# input param check
if len(data) != 3:
sde_dbg_evtlog_log_["data"] = tmp
self.default_parse(sde_dbg_evtlog_log_, output_fd)
return
tmp = tmp + ((50 - len(str(sde_dbg_evtlog_log_["data"]))) * " ")
tmp = tmp + "==> "
status_bit = {
0: 'CMD_MODE_DMA_DONE',
1: 'CMD_STREAM0_FRAME_DONE',
2: 'CMD_STREAM1_FRAME_DONE',
3: 'CMD_STREAM2_FRAME_DONE',
4: 'VIDEO_MODE_FRAME_DONE',
5: 'BTA_DONE',
6: 'CMD_FRAME_DONE',
7: 'DYN_REFRESH_DONE',
8: 'DESKEW_DONE',
9: 'DYN_BLANK_DMA_DONE',
10: 'ERROR',
}
data[0] = 'ctrl' + data[0]
status = int(data[1], 16)
status_str = []
temp_status = status
for i in range(len(status_bit)):
if (temp_status == 0x0):
break
if (temp_status %2):
status_str.append(status_bit[i])
temp_status = temp_status >> 1
#status_str = [status_bit[i] for i in range(11) if (status & BIT(i))]
data[1] = 'status: [' + '|'.join(status_str) + ']'
if status & self.BIT(10):
error = int(data[2], 16)
err_list = []
# Reference: fucntion dsi_ctrl_handle_error_status() in dsi/dsi_ctrl.c
if error & 0x3000E00:
err_list.append('PHY contention')
if error & 0xE0:
err_list.append('TX timeout')
if error & 0xF0000:
err_list.append('FIFO overflow')
if error & 0xF00000:
err_list.append('FIFO underflow')
i