Blame src/libbluray/register.c

Packit 5e46da
/*
Packit 5e46da
 * This file is part of libbluray
Packit 5e46da
 * Copyright (C) 2010-2017  Petri Hintukainen <phintuka@users.sourceforge.net>
Packit 5e46da
 *
Packit 5e46da
 * This library is free software; you can redistribute it and/or
Packit 5e46da
 * modify it under the terms of the GNU Lesser General Public
Packit 5e46da
 * License as published by the Free Software Foundation; either
Packit 5e46da
 * version 2.1 of the License, or (at your option) any later version.
Packit 5e46da
 *
Packit 5e46da
 * This library is distributed in the hope that it will be useful,
Packit 5e46da
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e46da
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 5e46da
 * Lesser General Public License for more details.
Packit 5e46da
 *
Packit 5e46da
 * You should have received a copy of the GNU Lesser General Public
Packit 5e46da
 * License along with this library. If not, see
Packit 5e46da
 * <http://www.gnu.org/licenses/>.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
#if HAVE_CONFIG_H
Packit 5e46da
#include "config.h"
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#include "register.h"
Packit 5e46da
Packit 5e46da
#include "player_settings.h"
Packit 5e46da
Packit 5e46da
#include "util/attributes.h"
Packit 5e46da
#include "util/macro.h"
Packit 5e46da
#include "util/logging.h"
Packit 5e46da
#include "util/mutex.h"
Packit 5e46da
Packit 5e46da
#include <stdlib.h>
Packit 5e46da
#include <string.h>
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Initial values for player status/setting registers (5.8.2).
Packit 5e46da
 *
Packit 5e46da
 * PS in comment indicates player setting -> register can't be changed from movie object code.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
static const uint32_t bd_psr_init[BD_PSR_COUNT] = {
Packit 5e46da
    1,           /*     PSR0:  Interactive graphics stream number */
Packit 5e46da
    0xff,        /*     PSR1:  Primary audio stream number */
Packit 5e46da
    0x0fff0fff,  /*     PSR2:  PG TextST stream number and PiP PG stream number*/
Packit 5e46da
    1,           /*     PSR3:  Angle number */
Packit 5e46da
    0xffff,      /*     PSR4:  Title number */
Packit 5e46da
    0xffff,      /*     PSR5:  Chapter number */
Packit 5e46da
    0,           /*     PSR6:  PlayList ID */
Packit 5e46da
    0,           /*     PSR7:  PlayItem ID */
Packit 5e46da
    0,           /*     PSR8:  Presentation time */
Packit 5e46da
    0,           /*     PSR9:  Navigation timer */
Packit 5e46da
    0xffff,      /*     PSR10: Selected button ID */
Packit 5e46da
    0,           /*     PSR11: Page ID */
Packit 5e46da
    0xff,        /*     PSR12: User style number */
Packit 5e46da
    0xff,        /* PS: PSR13: User age */
Packit 5e46da
    0xffff,      /*     PSR14: Secondary audio stream number and secondary video stream number */
Packit 5e46da
                 /* PS: PSR15: player capability for audio */
Packit 5e46da
    BLURAY_ACAP_LPCM_48_96_SURROUND |
Packit 5e46da
    BLURAY_ACAP_LPCM_192_SURROUND   |
Packit 5e46da
    BLURAY_ACAP_DDPLUS_SURROUND     |
Packit 5e46da
    BLURAY_ACAP_DDPLUS_DEP_SURROUND |
Packit 5e46da
    BLURAY_ACAP_DTSHD_CORE_SURROUND |
Packit 5e46da
    BLURAY_ACAP_DTSHD_EXT_SURROUND  |
Packit 5e46da
    BLURAY_ACAP_DD_SURROUND         |
Packit 5e46da
    BLURAY_ACAP_MLP_SURROUND,
Packit 5e46da
Packit 5e46da
    0xffffff,    /* PS: PSR16: Language code for audio */
Packit 5e46da
    0xffffff,    /* PS: PSR17: Language code for PG and Text subtitles */
Packit 5e46da
    0xffffff,    /* PS: PSR18: Menu description language code */
Packit 5e46da
    0xffff,      /* PS: PSR19: Country code */
Packit 5e46da
                 /* PS: PSR20: Region code */ /* 1 - A, 2 - B, 4 - C */
Packit 5e46da
    BLURAY_REGION_B,
Packit 5e46da
                 /* PS: PSR21: Output mode preference */
Packit 5e46da
    BLURAY_OUTPUT_PREFER_2D,
Packit 5e46da
    0,           /*     PSR22: Stereoscopic status */
Packit 5e46da
    0,           /* PS: PSR23: Display capability */
Packit 5e46da
    0,           /* PS: PSR24: 3D capability */
Packit 5e46da
    0,           /* PS: PSR25: UHD capability */
Packit 5e46da
    0,           /* PS: PSR26: UHD display capability */
Packit 5e46da
    0,           /* PS: PSR27: HDR preference */
Packit 5e46da
    0,           /* PS: PSR28: SDR conversion preference */
Packit 5e46da
                 /* PS: PSR29: player capability for video */
Packit 5e46da
    BLURAY_VCAP_SECONDARY_HD |
Packit 5e46da
    BLURAY_VCAP_25Hz_50Hz,
Packit 5e46da
Packit 5e46da
    0x1ffff,     /* PS: PSR30: player capability for text subtitle */
Packit 5e46da
                 /* PS: PSR31: Player profile and version */
Packit 5e46da
    BLURAY_PLAYER_PROFILE_2_v2_0,
Packit 5e46da
    0,           /*     PSR32 */
Packit 5e46da
    0,           /*     PSR33 */
Packit 5e46da
    0,           /*     PSR34 */
Packit 5e46da
    0,           /*     PSR35 */
Packit 5e46da
    0xffff,      /*     PSR36: backup PSR4 */
Packit 5e46da
    0xffff,      /*     PSR37: backup PSR5 */
Packit 5e46da
    0,           /*     PSR38: backup PSR6 */
Packit 5e46da
    0,           /*     PSR39: backup PSR7 */
Packit 5e46da
    0,           /*     PSR40: backup PSR8 */
Packit 5e46da
    0,           /*     PSR41: */
Packit 5e46da
    0xffff,      /*     PSR42: backup PSR10 */
Packit 5e46da
    0,           /*     PSR43: backup PSR11 */
Packit 5e46da
    0xff,        /*     PSR44: backup PSR12 */
Packit 5e46da
    0,           /*     PSR45: */
Packit 5e46da
    0,           /*     PSR46: */
Packit 5e46da
    0,           /*     PSR47: */
Packit 5e46da
    0xffffffff,  /* PS: PSR48: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR49: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR50: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR51: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR52: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR53: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR54: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR55: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR56: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR57: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR58: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR59: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR60: Characteristic text caps */
Packit 5e46da
    0xffffffff,  /* PS: PSR61: Characteristic text caps */
Packit 5e46da
    /* 62-95:   reserved */
Packit 5e46da
    /* 96-111:  reserved for BD system use */
Packit 5e46da
    /* 112-127: reserved */
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * PSR ids for debugging
Packit 5e46da
 */
Packit 5e46da
static const char * const bd_psr_name[BD_PSR_COUNT] = {
Packit 5e46da
    "IG_STREAM_ID",
Packit 5e46da
    "PRIMARY_AUDIO_ID",
Packit 5e46da
    "PG_STREAM",
Packit 5e46da
    "ANGLE_NUMBER",
Packit 5e46da
    "TITLE_NUMBER",
Packit 5e46da
    "CHAPTER",
Packit 5e46da
    "PLAYLIST",
Packit 5e46da
    "PLAYITEM",
Packit 5e46da
    "TIME",
Packit 5e46da
    "NAV_TIMER",
Packit 5e46da
    "SELECTED_BUTTON_ID",
Packit 5e46da
    "MENU_PAGE_ID",
Packit 5e46da
    "STYLE",
Packit 5e46da
    "PARENTAL",
Packit 5e46da
    "SECONDARY_AUDIO_VIDEO",
Packit 5e46da
    "AUDIO_CAP",
Packit 5e46da
    "AUDIO_LANG",
Packit 5e46da
    "PG_AND_SUB_LANG",
Packit 5e46da
    "MENU_LANG",
Packit 5e46da
    "COUNTRY",
Packit 5e46da
    "REGION",
Packit 5e46da
    "OUTPUT_PREFER",
Packit 5e46da
    "3D_STATUS",
Packit 5e46da
    "DISPLAY_CAP",
Packit 5e46da
    "3D_CAP",
Packit 5e46da
    //"PSR_VIDEO_CAP",
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * data
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
typedef struct {
Packit 5e46da
    void *handle;
Packit 5e46da
    void (*cb)(void *, BD_PSR_EVENT*);
Packit 5e46da
} PSR_CB_DATA;
Packit 5e46da
Packit 5e46da
struct bd_registers_s
Packit 5e46da
{
Packit 5e46da
    uint32_t     psr[BD_PSR_COUNT];
Packit 5e46da
    uint32_t     gpr[BD_GPR_COUNT];
Packit 5e46da
Packit 5e46da
    /* callbacks */
Packit 5e46da
    unsigned     num_cb;
Packit 5e46da
    PSR_CB_DATA *cb;
Packit 5e46da
Packit 5e46da
    BD_MUTEX     mutex;
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * init / free
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
BD_REGISTERS *bd_registers_init(void)
Packit 5e46da
{
Packit 5e46da
    BD_REGISTERS *p = calloc(1, sizeof(BD_REGISTERS));
Packit 5e46da
Packit 5e46da
    if (p) {
Packit 5e46da
        memcpy(p->psr, bd_psr_init, sizeof(bd_psr_init));
Packit 5e46da
Packit 5e46da
        bd_mutex_init(&p->mutex);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return p;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void bd_registers_free(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    if (p) {
Packit 5e46da
        bd_mutex_destroy(&p->mutex);
Packit 5e46da
Packit 5e46da
        X_FREE(p->cb);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    X_FREE(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * PSR lock / unlock
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
void bd_psr_lock(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    bd_mutex_lock(&p->mutex);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void bd_psr_unlock(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    bd_mutex_unlock(&p->mutex);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * PSR change callback register / unregister
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
void bd_psr_register_cb  (BD_REGISTERS *p, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle)
Packit 5e46da
{
Packit 5e46da
    /* no duplicates ! */
Packit 5e46da
    PSR_CB_DATA *cb;
Packit 5e46da
    unsigned i;
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    for (i = 0; i < p->num_cb; i++) {
Packit 5e46da
        if (p->cb[i].handle == cb_handle && p->cb[i].cb == callback) {
Packit 5e46da
Packit 5e46da
            bd_psr_unlock(p);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    cb = realloc(p->cb, (p->num_cb + 1) * sizeof(PSR_CB_DATA));
Packit 5e46da
    if (cb) {
Packit 5e46da
        p->cb = cb;
Packit 5e46da
        p->cb[p->num_cb].cb     = callback;
Packit 5e46da
        p->cb[p->num_cb].handle = cb_handle;
Packit 5e46da
        p->num_cb++;
Packit 5e46da
    } else {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_psr_register_cb(): realloc failed\n");
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void bd_psr_unregister_cb(BD_REGISTERS *p, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle)
Packit 5e46da
{
Packit 5e46da
    unsigned i = 0;
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    while (i < p->num_cb) {
Packit 5e46da
        if (p->cb[i].handle == cb_handle && p->cb[i].cb == callback) {
Packit 5e46da
            if (--p->num_cb && i < p->num_cb) {
Packit 5e46da
                memmove(p->cb + i, p->cb + i + 1, sizeof(PSR_CB_DATA) * (p->num_cb - i));
Packit 5e46da
                continue;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
        i++;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * PSR state save / restore
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
void bd_psr_save_state(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    /* store registers 4-8 and 10-12 to backup registers */
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    memcpy(p->psr + 36, p->psr + 4,  sizeof(uint32_t) * 5);
Packit 5e46da
    memcpy(p->psr + 42, p->psr + 10, sizeof(uint32_t) * 3);
Packit 5e46da
Packit 5e46da
    /* generate save event */
Packit 5e46da
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        BD_PSR_EVENT ev;
Packit 5e46da
        ev.ev_type = BD_PSR_SAVE;
Packit 5e46da
        ev.psr_idx = -1;
Packit 5e46da
        ev.old_val = 0;
Packit 5e46da
        ev.new_val = 0;
Packit 5e46da
Packit 5e46da
        unsigned j;
Packit 5e46da
        for (j = 0; j < p->num_cb; j++) {
Packit 5e46da
            p->cb[j].cb(p->cb[j].handle, &ev;;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void bd_psr_reset_backup_registers(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    /* init backup registers to default */
Packit 5e46da
    memcpy(p->psr + 36, bd_psr_init + 36, sizeof(uint32_t) * 5);
Packit 5e46da
    memcpy(p->psr + 42, bd_psr_init + 42, sizeof(uint32_t) * 3);
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void bd_psr_restore_state(BD_REGISTERS *p)
Packit 5e46da
{
Packit 5e46da
    uint32_t old_psr[13];
Packit 5e46da
    uint32_t new_psr[13];
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        memcpy(old_psr, p->psr, sizeof(old_psr[0]) * 13);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /* restore backup registers */
Packit 5e46da
    memcpy(p->psr + 4,  p->psr + 36, sizeof(uint32_t) * 5);
Packit 5e46da
    memcpy(p->psr + 10, p->psr + 42, sizeof(uint32_t) * 3);
Packit 5e46da
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        memcpy(new_psr, p->psr, sizeof(new_psr[0]) * 13);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /* init backup registers to default */
Packit 5e46da
    memcpy(p->psr + 36, bd_psr_init + 36, sizeof(uint32_t) * 5);
Packit 5e46da
    memcpy(p->psr + 42, bd_psr_init + 42, sizeof(uint32_t) * 3);
Packit 5e46da
Packit 5e46da
    /* generate restore events */
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        BD_PSR_EVENT ev;
Packit 5e46da
        unsigned     i, j;
Packit 5e46da
Packit 5e46da
        ev.ev_type = BD_PSR_RESTORE;
Packit 5e46da
Packit 5e46da
        for (i = 4; i < 13; i++) {
Packit 5e46da
            if (i != PSR_NAV_TIMER) {
Packit 5e46da
Packit 5e46da
                ev.psr_idx = i;
Packit 5e46da
                ev.old_val = old_psr[i];
Packit 5e46da
                ev.new_val = new_psr[i];
Packit 5e46da
Packit 5e46da
                for (j = 0; j < p->num_cb; j++) {
Packit 5e46da
                    p->cb[j].cb(p->cb[j].handle, &ev;;
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * GPR read / write
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
int bd_gpr_write(BD_REGISTERS *p, unsigned int reg, uint32_t val)
Packit 5e46da
{
Packit 5e46da
    if (reg >= BD_GPR_COUNT) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_gpr_write(%d): invalid register\n", reg);
Packit 5e46da
        return -1;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    p->gpr[reg] = val;
Packit 5e46da
    return 0;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
uint32_t bd_gpr_read(BD_REGISTERS *p, unsigned int reg)
Packit 5e46da
{
Packit 5e46da
    if (reg >= BD_GPR_COUNT) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_gpr_read(%d): invalid register\n", reg);
Packit 5e46da
        return 0;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return p->gpr[reg];
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * PSR read / write
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
uint32_t bd_psr_read(BD_REGISTERS *p, unsigned int reg)
Packit 5e46da
{
Packit 5e46da
    uint32_t val;
Packit 5e46da
Packit 5e46da
    if (reg >= BD_PSR_COUNT) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_psr_read(%d): invalid register\n", reg);
Packit 5e46da
        return -1;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    val = p->psr[reg];
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
Packit 5e46da
    return val;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
int bd_psr_setting_write(BD_REGISTERS *p, unsigned int reg, uint32_t val)
Packit 5e46da
{
Packit 5e46da
    if (reg >= BD_PSR_COUNT) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_psr_write(%d, %d): invalid register\n", reg, val);
Packit 5e46da
        return -1;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    if (p->psr[reg] == val) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_psr_write(%d, %d): no change in value\n", reg, val);
Packit 5e46da
    } else if (bd_psr_name[reg]) {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_psr_write(): PSR%-4d (%s) 0x%x -> 0x%x\n", reg, bd_psr_name[reg], p->psr[reg], val);
Packit 5e46da
    } else {
Packit 5e46da
        BD_DEBUG(DBG_BLURAY, "bd_psr_write(): PSR%-4d 0x%x -> 0x%x\n", reg, p->psr[reg], val);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        BD_PSR_EVENT ev;
Packit 5e46da
        unsigned i;
Packit 5e46da
Packit 5e46da
        ev.ev_type = p->psr[reg] == val ? BD_PSR_WRITE : BD_PSR_CHANGE;
Packit 5e46da
        ev.psr_idx = reg;
Packit 5e46da
        ev.old_val = p->psr[reg];
Packit 5e46da
        ev.new_val = val;
Packit 5e46da
Packit 5e46da
        p->psr[reg] = val;
Packit 5e46da
Packit 5e46da
        for (i = 0; i < p->num_cb; i++) {
Packit 5e46da
            p->cb[i].cb(p->cb[i].handle, &ev;;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
    } else {
Packit 5e46da
Packit 5e46da
        p->psr[reg] = val;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
Packit 5e46da
    return 0;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
int bd_psr_write(BD_REGISTERS *p, unsigned int reg, uint32_t val)
Packit 5e46da
{
Packit 5e46da
    if ((reg == 13) ||
Packit 5e46da
        (reg >= 15 && reg <= 21) ||
Packit 5e46da
        (reg >= 23 && reg <= 31) ||
Packit 5e46da
        (reg >= 48 && reg <= 61)) {
Packit 5e46da
      BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_psr_write(%d, %d): read-only register !\n", reg, val);
Packit 5e46da
      return -2;
Packit 5e46da
  }
Packit 5e46da
Packit 5e46da
  return bd_psr_setting_write(p, reg, val);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
int bd_psr_write_bits(BD_REGISTERS *p, unsigned int reg, uint32_t val, uint32_t mask)
Packit 5e46da
{
Packit 5e46da
    int result;
Packit 5e46da
Packit 5e46da
    if (mask == 0xffffffff) {
Packit 5e46da
        return bd_psr_write(p, reg, val);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    uint32_t psr_value = bd_psr_read(p, reg);
Packit 5e46da
    psr_value = (psr_value & (~mask)) | (val & mask);
Packit 5e46da
    result = bd_psr_write(p, reg, psr_value);
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
Packit 5e46da
    return result;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * save / restore registers between playback sessions
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
void registers_save(BD_REGISTERS *p, uint32_t *psr, uint32_t *gpr)
Packit 5e46da
{
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    memcpy(gpr, p->gpr, sizeof(p->gpr));
Packit 5e46da
    memcpy(psr, p->psr, sizeof(p->psr));
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void registers_restore(BD_REGISTERS *p, const uint32_t *psr, const uint32_t *gpr)
Packit 5e46da
{
Packit 5e46da
    uint32_t new_psr[13];
Packit 5e46da
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    memcpy(p->gpr, gpr, sizeof(p->gpr));
Packit 5e46da
    memcpy(p->psr, psr, sizeof(p->psr));
Packit 5e46da
Packit 5e46da
    memcpy(new_psr, p->psr, sizeof(new_psr[0]) * 13);
Packit 5e46da
Packit 5e46da
    /* generate restore events */
Packit 5e46da
    if (p->num_cb) {
Packit 5e46da
        BD_PSR_EVENT ev;
Packit 5e46da
        unsigned     i, j;
Packit 5e46da
Packit 5e46da
        ev.ev_type = BD_PSR_RESTORE;
Packit 5e46da
        ev.old_val = 0; /* not used with BD_PSR_RESTORE */
Packit 5e46da
Packit 5e46da
        for (i = 4; i < 13; i++) {
Packit 5e46da
            if (i != PSR_NAV_TIMER) {
Packit 5e46da
Packit 5e46da
                p->psr[i] = new_psr[i];
Packit 5e46da
Packit 5e46da
                ev.psr_idx = i;
Packit 5e46da
                ev.new_val = new_psr[i];
Packit 5e46da
Packit 5e46da
                for (j = 0; j < p->num_cb; j++) {
Packit 5e46da
                    p->cb[j].cb(p->cb[j].handle, &ev;;
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 *
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
int psr_init_3D(BD_REGISTERS *p, int initial_mode, int force)
Packit 5e46da
{
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    /* make automatic initialization to fail if app has already changed player profile */
Packit 5e46da
    if (!force) {
Packit 5e46da
        if ((bd_psr_read(p, PSR_PROFILE_VERSION) & BLURAY_PLAYER_PROFILE_VERSION_MASK) >= 0x0300) {
Packit 5e46da
            BD_DEBUG(DBG_BLURAY | DBG_CRIT, "psr_init_3D() failed: profile version already set to >= 0x0300 (profile 6)\n");
Packit 5e46da
            bd_psr_unlock(p);
Packit 5e46da
            return -1;
Packit 5e46da
        }
Packit 5e46da
        if (bd_psr_read(p, PSR_PROFILE_VERSION) & BLURAY_PLAYER_PROFILE_3D_FLAG) {
Packit 5e46da
            BD_DEBUG(DBG_BLURAY | DBG_CRIT, "psr_init_3D() failed: 3D already set in profile\n");
Packit 5e46da
            bd_psr_unlock(p);
Packit 5e46da
            return -1;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_OUTPUT_PREFER,
Packit 5e46da
                         BLURAY_OUTPUT_PREFER_3D);
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_DISPLAY_CAP,
Packit 5e46da
                         BLURAY_DCAP_1080p_720p_3D |
Packit 5e46da
                         BLURAY_DCAP_720p_50Hz_3D |
Packit 5e46da
                         BLURAY_DCAP_NO_3D_CLASSES_REQUIRED |
Packit 5e46da
                         BLURAY_DCAP_INTERLACED_3D |
Packit 5e46da
                         0);
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_3D_CAP,
Packit 5e46da
                         /* TODO */ 0xffffffff );
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_PROFILE_VERSION,
Packit 5e46da
                         BLURAY_PLAYER_PROFILE_5_v2_4);
Packit 5e46da
Packit 5e46da
    bd_psr_write(p, PSR_3D_STATUS,
Packit 5e46da
                 !!initial_mode);
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
Packit 5e46da
    return 0;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
int psr_init_UHD(BD_REGISTERS *p, int force)
Packit 5e46da
{
Packit 5e46da
    bd_psr_lock(p);
Packit 5e46da
Packit 5e46da
    /* make automatic initialization to fail if app has already changed player profile */
Packit 5e46da
    if (!force) {
Packit 5e46da
        if ((bd_psr_read(p, PSR_PROFILE_VERSION) & BLURAY_PLAYER_PROFILE_VERSION_MASK) >= 0x0300) {
Packit 5e46da
          BD_DEBUG(DBG_BLURAY | DBG_CRIT, "psr_init_UHD() failed: profile version already >= 0x0300\n");
Packit 5e46da
          bd_psr_unlock(p);
Packit 5e46da
          return -1;
Packit 5e46da
        }
Packit 5e46da
        if (bd_psr_read(p, PSR_PROFILE_VERSION) & BLURAY_PLAYER_PROFILE_3D_FLAG) {
Packit 5e46da
            BD_DEBUG(DBG_BLURAY | DBG_CRIT, "psr_init_UHD() failed: 3D already set in profile\n");
Packit 5e46da
            bd_psr_unlock(p);
Packit 5e46da
            return -1;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_UHD_CAP,
Packit 5e46da
                         /* TODO */ 0xffffffff );
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_UHD_DISPLAY_CAP,
Packit 5e46da
                         /* TODO */ 0xffffffff );
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_UHD_HDR_PREFER,
Packit 5e46da
                         /* TODO */ 0xffffffff );
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_UHD_SDR_CONV_PREFER,
Packit 5e46da
                         /* TODO */ 0 );
Packit 5e46da
Packit 5e46da
    bd_psr_setting_write(p, PSR_PROFILE_VERSION,
Packit 5e46da
                         BLURAY_PLAYER_PROFILE_6_v3_1);
Packit 5e46da
Packit 5e46da
    bd_psr_unlock(p);
Packit 5e46da
Packit 5e46da
    return 0;
Packit 5e46da
}