Update sreen driver and add fx9860 II driver
This commit is contained in:
parent
105eb7c482
commit
53a1ebf5a3
|
@ -26,7 +26,8 @@ extern void kvram_clr_str_area(int x, int y, int width, int height);
|
|||
extern void printk(int x, int y, char const *str, ...);
|
||||
|
||||
// Hardware specific function (do not use !)
|
||||
extern void t6k11_display(void *vram);
|
||||
extern void t6k11_lcd_driver(void *vram);
|
||||
extern void t6k11_variant_lcd_driver(uint8_t *vram);
|
||||
|
||||
//---
|
||||
// Timer functions.
|
||||
|
|
|
@ -1,16 +1,158 @@
|
|||
.global _t6k11_display
|
||||
.type _t6k11_display, @function
|
||||
|
||||
.text
|
||||
|
||||
.global _t6k11_lcd_driver
|
||||
.type _t6k11_lcd_driver, @function
|
||||
|
||||
.align 2
|
||||
/*
|
||||
** @proto: void _t6k11_lcd_driver(void *vram)
|
||||
**
|
||||
** @note:
|
||||
** This function will display the vram on the screen.
|
||||
** This is the T6K11 drivers, *DO NOT USE* this function if
|
||||
** you are not absolutly sure that what you are doing.
|
||||
**
|
||||
** @register list:
|
||||
** 0 - Display mode
|
||||
** 1 - Counter mode
|
||||
** 2 - Set analog control mode
|
||||
** 3 - Set alternating signal mode
|
||||
** 4 - Set X-address AND Set Y-address
|
||||
** 5 - Set Z-address
|
||||
** 6 - Contrast control
|
||||
** 7 - Data Write AND Data Read
|
||||
** 8 - Unknown, test mode only
|
||||
** 9 - Unknown, test mode only
|
||||
** 10 - Unknown, test mode only
|
||||
** 11 - Unknown, test mode only
|
||||
** 12 - D/A converter power control
|
||||
** 13 - Unknown, test mode only.
|
||||
** 14 - Unknown, test mode only.
|
||||
** 15 - Unknown, test mode only.
|
||||
**
|
||||
*/
|
||||
_t6k11_lcd_driver:
|
||||
! To avoid reentrace with the Video
|
||||
! RAM and I/O opetation, we need to
|
||||
! display data using atomic operation.
|
||||
! The next part *SHOULD* be exception save !
|
||||
mov.l .sr_int_msk, r1 ! Get SR mask for interrupt blocking.
|
||||
stc sr, r0 ! Save current SR register data.
|
||||
mov r0, r2 ! Get SR register data.
|
||||
or r1, r2 ! Set SR.BL = 1 and SR.IMASK = 0b1111
|
||||
ldc r2, sr ! Update SR register
|
||||
|
||||
! Stack management
|
||||
mov.l r8, @-r15 ! save r8 register.
|
||||
mov.l r0, @-r15 ! save SR register.
|
||||
|
||||
! Get LCD register addresses.
|
||||
mov.l .LCD_register_selector, r0 ! r0 = LCD register selector address.
|
||||
mov.l .LCD_data_register, r1 ! r1 = LCD data register.
|
||||
|
||||
! Set the X-adress counter to up-mode.
|
||||
! @note:
|
||||
! The X-address counter is used
|
||||
! for the row and the Y-addresss counter
|
||||
! for the column.
|
||||
mov #1, r2 ! r0 = counter mode register address.
|
||||
mov.b r2, @r0 ! Select the counter register.
|
||||
mov #1, r3 ! r0 = Y-address counter "Yup" mode.
|
||||
mov.b r3, @r1 ! Set the Y-address counter register to "Yup" mode.
|
||||
|
||||
|
||||
! "pre-generate" register data
|
||||
! r0 - LCD register selector
|
||||
! r1 - LCD data register
|
||||
! r2 - X-address / Y-address counter register
|
||||
! r3 - data write address
|
||||
! r4 - vram
|
||||
! r5 - row counter
|
||||
! r6 - Y-address counter
|
||||
! r7 - X-address counter
|
||||
mov #4, r2 ! X-address / Y-address counter.
|
||||
mov #7, r3 ! Data Write register
|
||||
mov #64, r5 ! Row counter
|
||||
mov #0, r6 ! Y-address counter (column, alway 0)
|
||||
mov #192, r7 ! X-address counter (row, 192 = 0, see documentation)
|
||||
|
||||
row_loop:
|
||||
! Select the X-address / Y-address counter.
|
||||
mov.b r2, @r0 ! Select X/Y address counter register.
|
||||
|
||||
! Update X-address counter / Reset the Y-address counter
|
||||
mov.b r7, @r1 ! Set X-address counter to current row
|
||||
mov.b r6, @r1 ! Set Y-address counter to 0
|
||||
|
||||
! Select Data write register.
|
||||
mov.b r3, @r0 ! Select Data Write register
|
||||
|
||||
! Avoid loop, so write line manually.
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
mov.b @r4+, r8
|
||||
mov.b r8, @r1
|
||||
|
||||
! Check next line.
|
||||
dt r5 ! if (--r5) == 0...
|
||||
bf.s row_loop ! ...if not, jump at <row_loop>
|
||||
add #1, r7 ! (db) update row counter.
|
||||
|
||||
exit_part:
|
||||
! Exit properly
|
||||
ldc.l @r15+, sr ! restore SR register
|
||||
mov.l @r15+, r8 ! resotre r8 register
|
||||
rts ! exit.
|
||||
nop ! (db) nop.
|
||||
|
||||
.align 4
|
||||
.LCD_register_selector: .long 0xb4000000 /* LCD register selector */
|
||||
.LCD_data_register: .long 0xb4010000 /* LCD data register */
|
||||
.sr_int_msk: .long 0x100000f0 /* SR interrupt mask */
|
||||
.end
|
||||
|
||||
|
||||
/*
|
||||
NOTE: OLD BUT FAST AND NOT SAFE
|
||||
NOTE: FOR MULTIPLE PROCESS !
|
||||
_t6k11_display(void *vram)
|
||||
This function will display the vram on the screen.
|
||||
This is the T6K11 drivers, DO NOT USE this function if you are
|
||||
not absolutly sure that what you are doing.
|
||||
|
||||
TODO: use DMA ?
|
||||
*/
|
||||
|
||||
# register organisation:
|
||||
# r0 Y axis loop.
|
||||
# r1 LCD register selector.
|
||||
|
@ -49,7 +191,7 @@ _t6k11_display:
|
|||
mov.l @r15+, r9
|
||||
rts
|
||||
mov.l @r15+, r8
|
||||
|
||||
.align 4
|
||||
1: .long 0xb4000000 /* LCD register selector */
|
||||
2: .long 0xb4010000 /* LCD data register */
|
||||
*/
|
||||
!.align 4
|
||||
!1: .long 0xb4000000 /* LCD register selector */
|
||||
!2: .long 0xb4010000 /* LCD data register */
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <kernel/util.h>
|
||||
#include <kernel/atomic.h>
|
||||
|
||||
// Internal symbols
|
||||
static volatile uint8_t *sel = (void *)0xb4000000;
|
||||
static volatile uint8_t *cmd = (void *)0xb4010000;
|
||||
|
||||
static void command(uint8_t reg, uint8_t data)
|
||||
{
|
||||
*sel = reg;
|
||||
*cmd = data;
|
||||
}
|
||||
|
||||
void t6k11_variant_lcd_driver(uint8_t *vram)
|
||||
{
|
||||
int y;
|
||||
|
||||
// Start atomic operations
|
||||
atomic_start();
|
||||
|
||||
y = -1;
|
||||
while (++y < 64)
|
||||
{
|
||||
// Row selector
|
||||
command(8, y | 0x80);
|
||||
command(8, 4);
|
||||
|
||||
// Send the row's data to the device
|
||||
// @note: Unroll the loop for more speed (?)
|
||||
*sel = 10;
|
||||
*cmd = vram[0];
|
||||
*cmd = vram[1];
|
||||
*cmd = vram[2];
|
||||
*cmd = vram[3];
|
||||
|
||||
*cmd = vram[4];
|
||||
*cmd = vram[5];
|
||||
*cmd = vram[6];
|
||||
*cmd = vram[7];
|
||||
|
||||
*cmd = vram[8];
|
||||
*cmd = vram[9];
|
||||
*cmd = vram[10];
|
||||
*cmd = vram[11];
|
||||
|
||||
*cmd = vram[12];
|
||||
*cmd = vram[13];
|
||||
*cmd = vram[14];
|
||||
*cmd = vram[15];
|
||||
|
||||
// Update vram ptr
|
||||
vram = &vram[16];
|
||||
}
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
.text
|
||||
|
||||
.global _sched_context_switch
|
||||
.type _sched_context_switch, @function
|
||||
|
||||
.align 2
|
||||
/*
|
||||
** void sched_context_switch(common_context_t *current, common_context_t *next);
|
||||
**
|
||||
** @note:
|
||||
** r4 - current scheduler task
|
||||
** r5 - next task
|
||||
** r0 - tmp
|
||||
*/
|
||||
_sched_context_switch:
|
||||
! Save contexts arg
|
||||
mov.l r8, @-r15 ! save r8
|
||||
mov.l r9, @-r15 ! save r9
|
||||
mov r4, r8 ! save current context into unbankable reg
|
||||
mov r5, r9 ! save next context into unbankable reg
|
||||
|
||||
|
||||
! Update SR register to block interrupt / exception and
|
||||
! switch register bank to simalate system call.
|
||||
! @note:
|
||||
! Normaly this is the TMU0 interrupt so the interrupt
|
||||
! and register banck is already switchted BUT durring the
|
||||
! bootstrap part, the kernel call this function in "user"
|
||||
! context. This is why we force update CPU configuration.
|
||||
mov.l .sr_msk, r1 ! get mask for SR.BL = 1, SR.RB = 1 and SR.IMASK = 0b1111
|
||||
stc sr, r0 ! get SR register
|
||||
or r1, r0 ! set mask for BL, RB and IMASK
|
||||
ldc r0, sr ! update SR regsiter
|
||||
|
||||
|
||||
! Restore context arg
|
||||
mov r8, r4 ! restore current context
|
||||
mov r9, r5 ! restore next context
|
||||
mov.l @r15+, r9 ! restore r9
|
||||
mov.l @r15+, r8 ! restore r8
|
||||
|
||||
save_current_context:
|
||||
! Check current process
|
||||
! @note: current process can be NULL !
|
||||
tst r4, r4 ! if current task == NULL...
|
||||
bt context_load ! ...if yes, jump at <context_switch>
|
||||
add #84, r4 ! get &process->context (end)
|
||||
|
||||
! save current context
|
||||
!sts.l pr, @-r4 ! get pr regsiter
|
||||
stc.l spc, @-r4 ! get spc regsiter
|
||||
stc.l ssr, @-r4 ! get ssr regsiter
|
||||
sts.l mach, @-r4 ! get mach regsiter
|
||||
sts.l macl, @-r4 ! get macl regsiter
|
||||
stc.l gbr, @-r4 ! get gbr regsiter
|
||||
mov.l r15, @-r4 ! get r15 register
|
||||
mov.l r14, @-r4 ! get r14 regsiter
|
||||
mov.l r13, @-r4 ! get r13 regsiter
|
||||
mov.l r12, @-r4 ! get r12 regsiter
|
||||
mov.l r11, @-r4 ! get r11 regsiter
|
||||
mov.l r10, @-r4 ! get r10 regsiter
|
||||
mov.l r9, @-r4 ! get r9 regsiter
|
||||
mov.l r8, @-r4 ! get r8 regsiter
|
||||
stc.l R7_BANK, @-r4 ! get "process" r7 regsiter
|
||||
stc.l R6_BANK, @-r4 ! get "process" r6 regsiter
|
||||
stc.l R5_BANK, @-r4 ! get "process" r5 regsiter
|
||||
stc.l R4_BANK, @-r4 ! get "process" r4 regsiter
|
||||
stc.l R3_BANK, @-r4 ! get "process" r3 regsiter
|
||||
stc.l R2_BANK, @-r4 ! get "process" r2 regsiter
|
||||
stc.l R1_BANK, @-r4 ! get "process" r1 regsiter
|
||||
stc.l R0_BANK, @-r4 ! get "process" r0 regsiter
|
||||
|
||||
|
||||
context_load:
|
||||
! Load next process
|
||||
! @note: next process can not be NULL !
|
||||
ldc.l @r5+, R0_BANK ! set "process" r0 regsiter
|
||||
ldc.l @r5+, R1_BANK ! set "process" r1 regsiter
|
||||
ldc.l @r5+, R2_BANK ! set "process" r2 regsiter
|
||||
ldc.l @r5+, R3_BANK ! set "process" r3 regsiter
|
||||
ldc.l @r5+, R4_BANK ! set "process" r4 regsiter
|
||||
ldc.l @r5+, R5_BANK ! set "process" r5 regsiter
|
||||
ldc.l @r5+, R6_BANK ! set "process" r6 regsiter
|
||||
ldc.l @r5+, R7_BANK ! set "process" r7 regsiter
|
||||
mov.l @r5+, r8 ! set r8 regsiter
|
||||
mov.l @r5+, r9 ! set r9 regsiter
|
||||
mov.l @r5+, r10 ! set r10 regsiter
|
||||
mov.l @r5+, r11 ! set r11 regsiter
|
||||
mov.l @r5+, r12 ! set r12 regsiter
|
||||
mov.l @r5+, r13 ! set r13 regsiter
|
||||
mov.l @r5+, r14 ! set r14 regsiter
|
||||
mov.l @r5+, r15 ! set r15 register
|
||||
ldc.l @r5+, gbr ! set gbr regsiter
|
||||
lds.l @r5+, macl ! set macl regsiter
|
||||
lds.l @r5+, mach ! set mach regsiter
|
||||
ldc.l @r5+, ssr ! set ssr regsiter
|
||||
ldc.l @r5+, spc ! set spc regsiter
|
||||
!lds.l @r5+, pr ! set pr regsiter
|
||||
|
||||
|
||||
! Process switch
|
||||
rte ! use RTE to switch process
|
||||
nop ! (db) nop
|
||||
|
||||
.align 4
|
||||
.sr_msk: .long 0x700000f0
|
||||
.end
|
|
@ -198,7 +198,7 @@ process_switch:
|
|||
.sched_schedule: .long _sched_schedule
|
||||
.timer_tstr_register: .long 0xa4490004
|
||||
.timer_unf_field: .long 0x00000100
|
||||
#ifndef __SCHED_DEBUG__
|
||||
#ifdef __SCHED_DEBUG__
|
||||
.sched_debug: .long _sched_debug
|
||||
#endif
|
||||
.end
|
||||
|
|
|
@ -13,7 +13,7 @@ uint32_t sched_timer_tstr_bit = 0;
|
|||
//void sched_handler(void);
|
||||
|
||||
//FIXME: remove me and wrap timer interrupt when occur !!
|
||||
static void scheduler_timer_callback(void)
|
||||
/*static void scheduler_timer_callback(void)
|
||||
{
|
||||
common_context_t *context_current;
|
||||
common_context_t *context_next;
|
||||
|
@ -38,7 +38,7 @@ static void scheduler_timer_callback(void)
|
|||
|
||||
// Context switch
|
||||
sched_context_switch(context_current, context_next);
|
||||
}
|
||||
}*/
|
||||
|
||||
void sched_start(void)
|
||||
{
|
||||
|
@ -93,7 +93,6 @@ void sched_start(void)
|
|||
// @note: I use Po/4 on TMU prescaler
|
||||
// TODO: generate quantum and quantum counter for preemption !
|
||||
uint32_t ticks = (per_freq / 4) / 16;
|
||||
//sched_timer_id = timer_install(scheduler_timer_callback, NULL, ticks, 0);
|
||||
sched_timer_id = timer_install(NULL, NULL, ticks, 0);
|
||||
sched_timer_address = (uint32_t)&SH7305_TMU.TIMER[sched_timer_id].TCR;
|
||||
sched_timer_intevt = 0x400 + (0x20 * sched_timer_id);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <kernel/font.h>
|
||||
#include <kernel/devices/display.h>
|
||||
#include <kernel/atomic.h>
|
||||
|
||||
// Font bitmap.
|
||||
static const uint8_t kernel_font_bitmap[] = {
|
||||
|
@ -55,9 +56,11 @@ static void font_draw_core(struct font_block_s *fblock)
|
|||
// this is why we use y << 2 because 2^2 = 4.
|
||||
vram_offset_y = fblock->y << 2;
|
||||
|
||||
// Start atomic operations
|
||||
atomic_start();
|
||||
|
||||
// Draw character, pixer per pixel... (x_x)
|
||||
// TODO: update me !!
|
||||
// TODO: atomic operation !!
|
||||
y = -1;
|
||||
while (++y < fblock->height)
|
||||
{
|
||||
|
@ -80,6 +83,9 @@ static void font_draw_core(struct font_block_s *fblock)
|
|||
fblock->bitmap.y = fblock->bitmap.y + KERNEL_FONT_BITMAP_WIDTH;
|
||||
vram_offset_y = vram_offset_y + 4;
|
||||
}
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,7 +30,11 @@ void kvram_clear(void)
|
|||
void kvram_display(void)
|
||||
{
|
||||
//TODO: handle screen hadware !
|
||||
t6k11_display(vram);
|
||||
//TODO: load dynamically screen driver during the boot
|
||||
if (*(uint8_t*)0xa0010021 == '3')
|
||||
t6k11_variant_lcd_driver((void*)vram);
|
||||
else
|
||||
t6k11_lcd_driver(vram);
|
||||
}
|
||||
|
||||
/* kvram_scroll() - Scroll up the Video RAM */
|
||||
|
@ -150,6 +154,9 @@ void kvram_clr_str_area(int x, int y, int width, int height)
|
|||
// Get VRAM offset
|
||||
vram_offset_y = y << 2;
|
||||
|
||||
// Start atomic operations
|
||||
atomic_start();
|
||||
|
||||
//DEbug
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "kvram_clr_str_area debug !");
|
||||
|
@ -176,6 +183,8 @@ void kvram_clr_str_area(int x, int y, int width, int height)
|
|||
vram_offset_y = vram_offset_y + 4;
|
||||
}
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_start();
|
||||
}
|
||||
|
||||
/* kvram_ascii() - Draw ASCII character into Video RAM */
|
||||
|
|
Loading…
Reference in New Issue