diff options
Diffstat (limited to 'driver/hdm-dim2/dim2_hal.c')
-rw-r--r-- | driver/hdm-dim2/dim2_hal.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/driver/hdm-dim2/dim2_hal.c b/driver/hdm-dim2/dim2_hal.c index 022df5c..6f2b6e4 100644 --- a/driver/hdm-dim2/dim2_hal.c +++ b/driver/hdm-dim2/dim2_hal.c @@ -135,15 +135,34 @@ static void free_dbr(int offs, int size) /* -------------------------------------------------------------------------- */ -static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) +static void dim2_transfer_madr(u32 val) { - dimcb_io_write(&g.dim2->MADR, ctr_addr); + dimcb_io_write(&g.dim2->MADR, val); - /* wait till transfer is completed */ + /* wait for transfer completion */ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) continue; dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ +} + +static void dim2_clear_dbr(u16 addr, u16 size) +{ + enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; + + u16 const end_addr = addr + size; + u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dimcb_io_write(&g.dim2->MDAT0, 0); + + for (; addr < end_addr; addr++) + dim2_transfer_madr(cmd | addr); +} + +static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) +{ + dim2_transfer_madr(ctr_addr); return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); } @@ -168,13 +187,7 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) dimcb_io_write(&g.dim2->MDWE2, mask[2]); dimcb_io_write(&g.dim2->MDWE3, mask[3]); - dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) @@ -793,6 +806,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, sync_init(ch, ch_address / 2, bytes_per_frame); + dim2_clear_dbr(ch->dbr_addr, ch->dbr_size); dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, ch->dbr_addr, ch->dbr_size, 0, true); |